我可以命名的三个优势,使用 double (或 float),而不是的 decimal:

  1. 使用较少的记忆。
  2. 速度更快,因为浮点的数学作业本身支持的处理器。
  3. 可以代表较大范围的数字。

但是,这些优势,似乎只适用于计算密集行动,诸如那些被发现在模拟软件。当然,加倍时,不应使用精确是必需的,例如财务计算。所以是否有任何实际的原因,没有选择 double (或 float),而不是的 decimal 在"正常"的应用?

编辑,以增加:感谢所有伟大的回应,我了解到他们。

一个进一步问题:几个人指出,加倍,可以更精确表示真实数字。当时宣布我将认为,他们通常更准确地代表了他们。但它是一个真实的陈述的准确度可能降低(有时大大)当浮点运行?

有帮助吗?

解决方案

我认为你已经很好地总结了这些优势。但是你缺少一点。 decimal 类型只是更多准确表示基数10 数字(例如用于货币/财务计算的数字)。通常, double 类型将提供至少同样精确的(如果我错了,有人纠正我),并且绝对提高任意实数的速度。简单的结论是:在考虑使用哪个时,总是使用 double ,除非你需要 base 10 精度, decimal 提供。

修改

关于您在操作后降低浮点数准确性的其他问题,这是一个稍微微妙的问题。实际上,在执行每个操作之后,精度(我在这里可互换地使用术语)将稳定地减少。这是由于两个原因:

  1. 某些数字(最明显的小数)无法以浮点形式真实表示
  2. 发生舍入错误,就像您手动执行计算一样。它在很大程度上取决于上下文(您正在执行多少操作)这些错误是否足够重要,无论如何都要多加考虑。
  3. 在所有情况下,如果你想比较理论上应该相等的两个浮点数(但是使用不同的计算得出),你需要允许一定程度的容差(多少变化,但通常是很小)。

    有关可以引入精度误差的特定情况的更详细概述,请参阅维基百科文章。最后,如果您想在机器级别对浮点数/操作进行认真深入(和数学)的讨论,请尝试阅读经常引用的文章 每个计算机科学家应该知道的关于浮点运算的内容

其他提示

你似乎有点在利用一个浮点类型。我倾向于设计小数在所有情况下,并依赖的分析器来让我知道,如果操作的十进制造瓶颈或缓慢的起伏。在这些情况下,我将"下铸造"双重或浮动,但是仅仅做它的境内,并仔细地设法处理精确度的损失通过限制数量的显着位数字的数学作正在进行的。

在一般情况下,如果你的价值是短暂(不重复使用),你在安全使用一个浮点类型。真正的问题与浮点类型是以下三个方案。

  1. 你们聚集的浮点值(在这种情况下精确的错误化合物)
  2. 你构建价值观的基础上浮点值(例如在递归算法)
  3. 你是做数学的一个非常广泛的数量有效数字(例如, 123456789.1 * .000000000000000987654321)

编辑

根据 参考文件C#小数:

十进制的 关键词表示一个 128位数据的类型。相比 浮点类型、小型 有一个更精确和较小的 范围,使其适用于 金融和货币计算。

所以澄清我的上述声明:

我倾向于设计小数在所有 情况,并依靠一个探查到我们 我知道,如果操作上是十进制的 造成瓶颈或缓慢的起伏。

我只有曾经工作过的行业小数都是有利的。如果你在工作上phsyics或图形的引擎,它可能更有利于设计一个浮点类型(float或双).

小数点并不是无限精确的(这是不可能表示无限的精确度对于非不可或缺的一个原始数据的类型),但它是更精确的比双:

  • 小数=28日至29日有效数字
  • 双=15-16日有效数字
  • 浮=7位有效数字

编辑2

响应 康拉德*鲁道夫's评论,项目#1(上述)是绝对正确的。聚集的不精确的化合物。看到下面的代码一个例子:

private const float THREE_FIFTHS = 3f / 5f;
private const int ONE_MILLION = 1000000;

public static void Main(string[] args)
{
    Console.WriteLine("Three Fifths: {0}", THREE_FIFTHS.ToString("F10"));
    float asSingle = 0f;
    double asDouble = 0d;
    decimal asDecimal = 0M;

    for (int i = 0; i < ONE_MILLION; i++)
    {
        asSingle += THREE_FIFTHS;
        asDouble += THREE_FIFTHS;
        asDecimal += (decimal) THREE_FIFTHS;
    }
    Console.WriteLine("Six Hundred Thousand: {0:F10}", THREE_FIFTHS * ONE_MILLION);
    Console.WriteLine("Single: {0}", asSingle.ToString("F10"));
    Console.WriteLine("Double: {0}", asDouble.ToString("F10"));
    Console.WriteLine("Decimal: {0}", asDecimal.ToString("F10"));
    Console.ReadLine();
}

这种产出如下:

Three Fifths: 0.6000000000
Six Hundred Thousand: 600000.0000000000
Single: 599093.4000000000
Double: 599999.9999886850
Decimal: 600000.0000000000

正如你可以看到,尽管我们正在增加从同一来源不断,结果双是小精确的(虽然可能会正确地),而浮动是远远不够精确,它已经减少到仅有的两位有效数字。

使用十进制为基10值,例如金融计算,正如其他人已经提出了建议。

但双一般是更精确的用于任意的计算值。

例如,如果你想的重量计算的每个线在一个投资组合,使用双作的结果将更多的几乎增加了100%。

在下面的例子中,doubleResult更接近1比decimalResult:

// Add one third + one third + one third with decimal
decimal decimalValue = 1M / 3M;
decimal decimalResult = decimalValue + decimalValue + decimalValue;
// Add one third + one third + one third with double
double doubleValue = 1D / 3D;
double doubleResult = doubleValue + doubleValue + doubleValue;

所以再次考虑的例子的投资组合:

  • 的市场价值中的每一行投资组合是货币价值,并可能最好的作为表示小数点。

  • 重每个行在投资组合(=市场价值/SUM(市场价值))通常更好的表示作为一倍。

当你不需要精确度时,使用double或float,例如,在我写的平台游戏中,我使用浮动来存储玩家的速度。显然我在这里不需要超精确,因为我最终会转向Int以在屏幕上绘图。

在某些会计中,请考虑使用整数类型或结合使用整数类型的可能性。例如,假设你操作的规则要求每个计算结果至少带有6个小数位,最终结果将四舍五入到最接近的便士。

计算100美元的1/6会产生$ 16.66666666666666 ...,因此工作表中的价值为16.666667美元。 double和decimal都应该准确地将结果产生到6位小数。但是,我们可以通过将结果转发为整数16666667来避免任何累积误差。每个后续计算都可以以相同的精度进行并类似地进行。继续这个例子,我计算了该金额的德克萨斯州销售税(16666667 * .0825 = 1375000)。添加两个(这是一个简短的工作表)1666667 + 1375000 = 18041667.将小数点移回给我们18.041667,或18.04美元。

虽然这个简短的例子不会产生使用double或decimal的累积误差,但是很容易显示简单地计算double或decimal并且继续前进会累积重大错误的情况。如果您在其下运行的规则需要有限的小数位数,则将每个值存储为整数乘以10 ^(所需的小数位数),然后除以10 ^(所需的小数位数)以获得实际值值将避免任何累积错误。

在没有发生几分钱的情况下(例如,自动售货机),根本没有理由使用非整数类型。简单地把它想象成便士,而不是美元。我看过代码,其中每个计算只涉及整个便士,但使用double会导致错误!仅整数数学删除了该问题。所以我的非常规答案是,如果可能的话,放弃双倍和小数。

如果你需要与其他语言或平台进行二进制交互,那么你可能需要使用标准化的float或double。

注:这个职位的信息为基础的小型的能力从 http://csharpindepth.com/Articles/General/Decimal.aspx 和我自己的解释,这意味着什么。我会假设双是正常的IEEE双精度。

注2:最小和最大的在这个岗位等都指的大小的数字。

赞成"decimal".

  • "decimal"可以表示确切的数字可以写作(足够短的)小数,双不能。这是重要的,在财务账目和类似的其它重要的是,结果完全匹配是什么人做的计算将得到。
  • "decimal"具有大得多的尾数比"双"。这意味着,对于价值观,在它的正常化的范围内"decimal"将有一个更精确度较高一倍以上。

弊的十进制的

  • 它会慢得多(我没有基准,但我猜至少一个数量级可能更大),小数将不从中获益的任何硬件加速和算术上,它将需要相对较昂贵的乘法/司通过权力的10(这是更昂贵的比乘法和dividion通过权力的2)匹配指数之前加/减,并把指数回到范围后乘/司。
  • 小数将溢出前面临的双重会。小数只能代表人数达到±296-1.通过比较可以双代表人数达到将近±21024
  • 小数将溢早。最小的数字表示在小数点±10-28 .通过比较可以双代表数值下降到2-149 (大约10-45)如果subnromal数字的支持和2-126 (大约10-38)如果他们不是。
  • 小数占用的两倍多,存作为一倍。

我看是的,你应该默认使用"decimal"钱工作和其他情况下匹配的人计算到底重要的是,应使用采用双重作为默认选择的余的时间。

如果您重视性能而不是正确性,请使用浮点数。

选择应用程序的功能类型。如果您需要财务分析中的精确度,您已回答了您的问题。但是,如果你的申请可以通过双倍估算你的确定。

您的申请是否需要快速计算,或者他是否会一直在世界上给您答案?这实际上取决于应用程序的类型。

图形饥饿?漂浮或双倍就足够了。财务数据分析,流星撞击行星的那种精确度?那些需要一点精度:)

Decimal有更宽的字节,CPU本身支持double。十进制是基数为10,因此在计算小数时会发生十进制到双精度转换。

For accounting - decimal
For finance - double
For heavy computation - double

请记住,.NET CLR仅支持Math.Pow(double,double)。不支持十进制。

.NET Framework 4

[SecuritySafeCritical]
public static extern double Pow(double x, double y);

如果该表示法比十进制显示短,则双值将默认序列化为科学计数法。 (例如.00000003将是3e-8)十进制值永远不会序列化为科学记数法。当序列化供外部消费时,这可能是一个考虑因素。

取决于您的需要。

因为float和double是二进制数据类型,所以在轮数中你有 一些 diifculties和errrors,所以例如double将会舍入0.1到0.100000001490116,double会也是1/3至0.33333334326441。简单地说,并非所有实数都具有双重类型的准确表示

幸运的是,C#还支持所谓的十进制浮点运算,其中数字通过十进制数字系统而不是二进制系统表示。因此,当存储和处理浮点数时,十进制浮点算术不会失去准确度。这使得它非常适合需要高精度的计算。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top