我经常看到人们在C#中使用double。我知道有些情况下double会丢失精度。 我的问题是什么时候应该使用double,什么时候应该使用decimal类型? 哪种类型适合于货币计算?(即大于1亿美元)
当需要进行科学计算或需要更大的范围时,应该使用double类型。而当需要高精度的小数计算时,则应该使用decimal类型。
对于货币计算,应该使用decimal类型。因为货币计算需要高精度小数,并且不能容忍任何形式的舍入误差。decimal类型可以提供可靠的结果,并且不会丢失精度。
我经常看到人们在C#中使用double。我知道有些情况下double会丢失精度。 我的问题是什么时候应该使用double,什么时候应该使用decimal类型? 哪种类型适合于货币计算?(即大于1亿美元)
当需要进行科学计算或需要更大的范围时,应该使用double类型。而当需要高精度的小数计算时,则应该使用decimal类型。
对于货币计算,应该使用decimal类型。因为货币计算需要高精度小数,并且不能容忍任何形式的舍入误差。decimal类型可以提供可靠的结果,并且不会丢失精度。
对于货币,始终使用十进制。这就是其被创建的原因。
如果数字必须正确相加或平衡,请使用十进制。这包括任何手动计算的财务存储或计算、分数或其他数字。
如果数字的精确值不重要,请为了提高速度而使用double。这包括图形、物理或其他物理科学计算中已经有“有效数字位数”的情况。
0.1 * 0.1 != 0.01
,因为0.1无法被完全表示。数学运算也会导致漂移——对于美分和美元进行加减运算可能得到像0.9999999999999这样的数字。toString()方法通过四舍五入来隐藏这个问题,但确切的比较立即就出现了错误。 - Daviddouble
不适用于表示金融价值,但是当你写到与 decimal
相比,double
不支持特定的舍入模式时,你确切指的是什么?据我所知,Math.Round
有多个重载方法,可以接受 MidpointRounding
参数,同时适用于 double
和 decimal
。 - vgru.NET类型 | C# 关键字 | 精度 |
---|---|---|
System.Single |
float | 约6-9位数 |
System.Double |
double | 约15-17位数 |
System.Decimal |
decimal | 28-29位数 |
我以前因为在处理大量数据时使用了错误的类型而受到过教训(好几年前):
对于float类型,最大只能处理到100万。
一个15位数的货币值:
对于double类型,最大只能处理到9万亿。但是在除法和比较方面更加复杂(我绝对不是浮点数和无理数的专家 - 可以看看Marc的观点)。混合使用decimal和double会导致问题:
精准逼近小数时,何时应该使用double而不是decimal?提供了一些类似且更深入的答案。在金融应用中使用如果一个浮点数用于数学或比较运算,而使用十进制数则可能产生不同的结果,因为浮点数可能不准确。
double
而不是decimal
是一种微观优化-这是我看待它的最简单方式。520,532.52
有8个有效数字,而 1,323,523.12
则有9个。参考链接:http://mathsfirst.massey.ac.nz/Algebra/Decimals/SigFig.htm - Royi Namirfloat
,double
和 decimal
链接已损坏。这里是关于这三种数值类型别名的最新 MSDN 文档链接:https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/floating-point-numeric-types - Mass Dot NetDecimal用于精确值,Double用于近似值。
USD: $12,345.67 USD (Decimal)
CAD: $13,617.27 (Decimal)
Exchange Rate: 1.102932 (Double)
对于货币来说,建议使用decimal
类型。虽然这会占用更多内存,但不像double
类型有时会遇到舍入问题。
1m/3m + 1m/3m == 2m/3m
。主要区别在于——有效数字位数更多,最重要的是:当操作除数中带有5的数字时,不会出现精度损失。例如,1m/5m + 1m/5m
将完全等于 2m/5m
。 - user2622016一定要在你处理货币计算时使用整数类型。
这一点不能够强调得太多,因为乍一看似乎浮点类型就足够了。
以下是 Python 代码示例:
>>> amount = float(100.00) # one hundred dollars
>>> print amount
100.0
>>> new_amount = amount + 1
>>> print new_amount
101.0
>>> print new_amount - amount
>>> 1.0
看起来相当正常。
现在再试试用 10^20
津巴布韦元:
>>> amount = float(1e20)
>>> print amount
1e+20
>>> new_amount = amount + 1
>>> print new_amount
1e+20
>>> print new_amount-amount
0.0
正如您所看到的,美元符号已经消失了。
如果您使用整数类型,则可以正常工作:
>>> amount = int(1e20)
>>> print amount
100000000000000000000
>>> new_amount = amount + 1
>>> print new_amount
100000000000000000001
>>> print new_amount - amount
1
int
而不是 decimal
(也许是出于性能原因)。避免使用 double
,而是使用 decimal
。Decimal 使用基数为 10 的指数,因此在解析类似于 0.1 的基数为 10 的值时,不会遇到与 double 相同的二进制舍入误差。 - BlueMonkMN