替身真的不适合用钱吗?

在 c # 中,我总是说 double 类型的变量不适合用于货币。所有奇怪的事情都可能发生。但我似乎不能创造一个例子来说明其中的一些问题。有人能举出这样的例子吗?

(编辑; 这篇文章最初被标记为 C # ; 一些回复提到了 decimal的具体细节,因此意味着 System.Decimal)。

(编辑2: 我特别要求一些 c # 代码,所以我不认为这只是语言不可知论)

19205 次浏览

非常,非常不合适,用小数。

double x = 3.65, y = 0.05, z = 3.7;
Console.WriteLine((x + y) == z); // false

(例如来自 Jon 的页面 给你-推荐阅读; -p)

舍入会有效地导致奇数错误。此外,与精确值进行比较是非常棘手的-您通常需要应用某种 ε 来检查实际值是否“接近”某个特定的值。

这里有一个具体的例子:

using System;


class Test
{
static void Main()
{
double x = 0.1;
double y = x + x + x;
Console.WriteLine(y == 0.3); // Prints False
}
}

是的,不合适。

如果我记得正确的话,double 有大约17个有效数字,所以通常舍入误差会发生在小数点后面很远的地方。大多数金融软件使用小数点后面的4个小数,这留下了13个小数的工作,所以最大的数字,你可以工作,为单一操作仍然是非常高的比美国国家债务。但是舍入误差会随着时间的推移而增加。如果你的软件运行很长时间,你最终会开始损失分。某些行动会让情况变得更糟。例如,将大量数据加入到小量数据中会导致精度的显著损失。

You need fixed point datatypes for money operations, most people don't mind if you lose a cent here and there but accountants aren't like most people..

编辑
根据这个网站的资料,双人间实际上有15到16个有效数字,而不是17个。

@ Jon Skeet 小数比 double 更合适,因为它的精度更高,28或29个有意义的小数。这意味着累积舍入误差变得重要的可能性更小。像 Boojum 提到的固定点数据类型(即表示美分或百分之一美分的整数)实际上更适合。

因为 decimal使用的比例因子是10的倍数,所以像0.1这样的数字可以精确地表示出来。本质上,十进制类型表示为1/10 ^ 1,而 double表示为104857/2 ^ 20(实际上它更像 非常大的数字/2 ^ 1023)。

一个 decimal可以精确地表示任何基数为10的最高28/29的有效数字(比如0.1) ,而一个 double则不能。

我的理解是,大多数金融系统使用整数来表示货币——也就是说,用美分来计算所有东西。

IEEE 双精度实际上 可以表示从 -2 ^ 53到 + 2 ^ 53范围内的所有整数。(黑客的乐趣,pg。262)如果你只使用加法、减法和乘法,并且把所有的东西都保持在这个范围内,那么你应该不会看到精度的损失。但我会对组织或者更复杂的行动非常警惕。

不,一个双精度数总是有舍入错误,如果你在.Net 上使用“十进制”..。

在不知道自己在做什么的情况下使用双倍是不合适的。

“ double”可以表示一万亿美元的数额,误差为1/90美分。所以你会得到非常精确的结果。想计算一下把一个人送上火星并让他活着回来要花多少钱吗?加倍就行了。

但是,对于金钱,往往有非常具体的规则说,某种计算必须给出某种结果,而不能给出其他结果。如果你计算的金额非常非常接近 $98.135,那么通常会有一个规则来决定结果应该是 $98.14还是 $98.13,你 必须的遵循这个规则并得到所需的结果。

取决于你住的地方,用64位整数来表示美分、便士、戈比或者任何你国家最小的单位通常都可以。例如,代表美分的64位有符号整数可以代表高达92,223万亿美元的价值。32位整数通常是不合适的。

实际上,只要你选择一个合适的单位,浮点 双倍非常适合表示金额。

参见 http://www.idinews.com/moneyRep.html

定点 很长也是如此,它们都消耗8字节,肯定比 十进制项消耗的16字节要好。

有些东西是否有效(例如产生预期的和正确的结果)不是投票或个人偏好的问题。一种技术要么有效,要么无效。