C# 双真的不适合钱吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/316727/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is a double really unsuitable for money?
提问by doekman
I always tell in c# a variable of type double is not suitable for money. All weird things could happen. But I can't seem to create an example to demonstrate some of these issues. Can anyone provide such an example?
我总是在 C# 中告诉一个 double 类型的变量不适合钱。所有奇怪的事情都有可能发生。但我似乎无法创建一个示例来演示其中一些问题。谁能提供这样的例子?
(edit; this post was originally tagged C#; some replies refer to specific details of decimal
, which therefore means System.Decimal
).
(编辑;这篇文章最初被标记为 C#;一些回复引用了 的具体细节decimal
,因此意味着System.Decimal
)。
(edit 2: I was specific asking for some c# code, so I don't think this is language agnostic only)
(编辑 2:我特别要求一些 c# 代码,所以我认为这不仅仅是语言不可知的)
采纳答案by Marc Gravell
回答by Jon Skeet
You will get odd errors effectively caused by rounding. In addition, comparisons with exact values are extremely tricky - you usually need to apply some sort of epsilon to check for the actual value being "near" a particular one.
你会得到由四舍五入引起的奇怪错误。此外,与精确值的比较非常棘手 - 您通常需要应用某种 epsilon 来检查实际值是否“接近”特定值。
Here's a concrete example:
这是一个具体的例子:
using System;
class Test
{
static void Main()
{
double x = 0.1;
double y = x + x + x;
Console.WriteLine(y == 0.3); // Prints False
}
}
回答by Mendelt
Yes it's unsuitable.
是的,不合适。
If I remember correctly double has about 17 significant numbers, so normally rounding errors will take place far behind the decimal point. Most financial software uses 4 decimals behind the decimal point, that leaves 13 decimals to work with so the maximum number you can work with for single operations is still very much higher than the USA national debt. But rounding errors will add up over time. If your software runs for a long time you'll eventually start losing cents. Certain operations will make this worse. For example adding large amounts to small amounts will cause a significant loss of precision.
如果我没记错的话,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..
你需要定点数据类型来进行货币操作,大多数人不介意你在这里和那里损失一分钱,但会计师不像大多数人..
edit
According to this site http://msdn.microsoft.com/en-us/library/678hzkk9.aspxDoubles actually have 15 to 16 significant digits instead of 17.
编辑
根据这个网站http://msdn.microsoft.com/en-us/library/678hzkk9.aspx双打实际上有 15 到 16 位有效数字而不是 17。
@Jon Skeet decimal is more suitable than double because of its higher precision, 28 or 29 significant decimals. That means less chance of accumulated rounding errors becoming significant. Fixed point datatypes (ie integers that represent cents or 100th of a cent like I've seen used) like Boojum mentions are actually better suited.
@Jon Skeet decimal 比 double 更合适,因为它具有更高的精度,28 或 29 位有效小数。这意味着累积舍入误差变得显着的可能性较小。像 Boojum 提到的定点数据类型(即代表美分或 100 分之一的整数,就像我见过的那样)实际上更适合。
回答by Richard Poole
Since decimal
uses a scaling factor of multiples of 10, numbers like 0.1 can be represented exactly. In essence, the decimal type represents this as 1 / 10 ^ 1, whereas a double
would represent this as 104857 / 2 ^ 20 (in reality it would be more like really-big-number/ 2 ^ 1023).
由于decimal
使用了 10 的倍数的比例因子,因此可以准确地表示 0.1 之类的数字。本质上,十进制类型将其表示为 1 / 10 ^ 1,而 adouble
将表示为 104857 / 2 ^ 20(实际上它更像是真正的大数/ 2 ^ 1023)。
A decimal
can exactly represent any base 10 value with up to 28/29 significant digits (like 0.1). A double
can't.
Adecimal
可以精确地表示最多 28/29 位有效数字(如 0.1)的任何以 10 为基数的值。一个double
不能。
回答by Boojum
My understanding is that most financial systems express currency using integers -- i.e., counting everything in cents.
我的理解是,大多数金融系统使用整数来表示货币——即,以美分计算一切。
IEEE double precision actually canrepresent all integers exactly in the range -2^53 through +2^53. (Hacker's Delight, pg. 262) If you use only addition, subtraction and multiplication, and keep everything to integers within this range then you should see no loss of precision. I'd be very wary of division or more complex operations, however.
IEEE 双精度实际上可以精确地表示 -2^53 到 +2^53 范围内的所有整数。(Hacker's Delight,第 262 页)如果您只使用加法、减法和乘法,并将所有内容保持在此范围内的整数,那么您应该不会看到精度损失。但是,我会非常警惕除法或更复杂的操作。
回答by Thomas Hansen
No a double will always have rounding errors, use "decimal" if you're on .Net...
没有双精度会总是有舍入错误,如果您在 .Net 上,请使用“十进制”...
回答by gnasher729
Using double when you don't know what you are doing is unsuitable.
当您不知道自己在做什么时使用 double 是不合适的。
"double" can represent an amount of a trillion dollars with an error of 1/90th of a cent. So you will get highly precise results. Want to calculate how much it costs to put a man on Mars and get him back alive? double will do just fine.
“double”可以代表一万亿美元的金额,误差为 1/90 分。因此,您将获得高度精确的结果。想计算将一个人送上火星并让他活着回来需要多少钱?double 就可以了。
But with money there are often very specific rules saying that a certain calculation must give a certain result and no other. If you calculate an amount that is very very very close to $98.135 then there will often be a rule that determines whether the result should be $98.14 or $98.13 and you mustfollow that rule and get the result that is required.
但是对于金钱,通常有非常具体的规则,即某个计算必须给出某个结果,而不能给出其他结果。如果您计算出的金额非常非常接近 98.135 美元,那么通常会有一个规则来确定结果是 98.14 美元还是 98.13 美元,您必须遵循该规则并获得所需的结果。
Depending on where you live, using 64 bit integers to represent cents or pennies or kopeks or whatever is the smallest unit in your country will usually work just fine. For example, 64 bit signed integers representing cents can represent values up to 92,223 trillion dollars. 32 bit integers are usually unsuitable.
根据您居住的地方,使用 64 位整数来表示美分或便士或戈比或您所在国家/地区的最小单位通常都可以正常工作。例如,代表美分的 64 位有符号整数可以代表高达 92,223 万亿美元的价值。32 位整数通常是不合适的。
回答by Conrad Weisert
Actually floating-point doubleis perfectly well suited to representing amounts of money as long as you pick a suitable unit.
实际上,只要您选择合适的单位,浮点双精度就非常适合表示金额。
See http://www.idinews.com/moneyRep.html
见http://www.idinews.com/moneyRep.html
So is fixed-point long. Either consumes 8 bytes, surely preferable to the 16 consumed by a decimalitem.
定点long 也是如此。要么消耗 8 个字节,肯定优于十进制项消耗的 16 个字节。
Whether or not something works (i.e. yields the expected and correct result) is not a matter of either voting or individual preference. A technique either works or it doesn't.
某事是否有效(即产生预期和正确的结果)与投票或个人偏好无关。一种技术要么有效,要么无效。