c#: sum of two double numbers problem
Possible Duplicate:
Why is floating point arithmetic in C# imprecise?
你好。我有以下问题:
1 | 43.65+61.11=104.75999999999999 |
小数正确:
1 | (decimal)43.65+(decimal)61.11=104.76 |
为什么加倍的结果是错误的?
这个问题及其答案是关于这个的大量信息-在.NET中十进制、浮点和双精度之间的差异?
引述:
For values which are"naturally exact
decimals" it's good to use decimal.
This is usually suitable for any
concepts invented by humans: financial
values are the most obvious example,
but there are others too. Consider the
score given to divers or ice skaters,
for example.For values which are more artefacts of
nature which can't really be measured
exactly anyway, float/double are more
appropriate. For example, scientific
data would usually be represented in
this form. Here, the original values
won't be"decimally accurate" to start
with, so it's not important for the
expected results to maintain the
"decimal accuracy". Floating binary
point types are much faster to work
with than decimals.
简短回答:浮点表示(如"double")本质上是不准确的。定点(如"小数")也是如此,但定点表示的不准确度是另一类。下面是一个简短的解释:http://effbot.org/pyfaq/why-are-floating-point-calculations-so-unaccurance.htm
你可以谷歌搜索"浮点不准确"或更多。
这并不完全是错的。它是与求和得到的二进制浮点数最接近的十进制表示。
问题是,由于使用了二进制尾数,所以ieee float不能精确地表示43.65+61.11。一些系统(如Python 2.7和VisualC++的标准I/O库)将绕过最简单的十进制,解析为相同的二进制,并打印预期的104.76。但所有这些系统在内部都得到了完全相同的答案。
有趣的是,十进制符号可以有限地表示任何有限的二进制分数,而相反的则不成立。如果人类有两个手指,计算机使用十态存储器,我们就不会有这个问题。-)
归根结底,浮点数是以二进制浮点数的形式存储的,和以10为基数的浮点数一样,有些数字在没有截断的情况下是无法存储的。以10为基数的1/3为例,即.3循环。当转换为二进制时,您要处理的数字是循环出现的。
我不同意浮点或双精度比十进制表示更准确或更不准确。它们和你选择的精度一样精确。然而,它们是一种不同的表示,不同的数字可以表示为整数,而不是以10为基数。
十进制以10为基数存储数字。这可能会给你预期的结果
因为double使用分数模型。任何小于1的数字都以x/y的形式表示。鉴于此信息,有些数字只能近似。使用十进制,而不是双精度计算。
请看这里了解一些光读数:)
十进制算术非常适合以10为基数的数字表示,因为10为基数的数字可以精确地以十进制表示。(这就是为什么货币总是以适当的货币类别存储,或存储在
ieee-754二进制数不能用
注意这个简单的程序和输出:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #include <stdio.h> int main(int argc, char* argv[]) { float f, g; double d, e; long double l, m; f=0.1; g=f*f; d=0.1; e=d*d; l=0.1; m=l*l; printf("%40.40f, %40.40f, %40.40Lf ", g, e, m); return 0; } $ ./fp 0.0100000007078051567077636718750000000000, 0.0100000000000000019428902930940239457414, 0.0100000000000000011102569059430467124372 |
这三种可能性都不能给出准确的答案,
但对货币使用十进制算术。
真的?下面的代码按预期返回104.76:
1 2 3 4 5 6 7 8 9 10 11 | class Program { static void Main(string[] args) { double d1 = 43.65; double d2 = 61.11; double d3 = d1 + d2; Console.WriteLine(d3); Console.ReadLine(); } } |
鉴于以下代码返回104.76000213623
1 2 3 4 5 6 7 8 9 10 11 | class Program { static void Main(string[] args) { float d1 = 43.65f; float d2 = 61.11f; double d3 = d1 + d2; Console.WriteLine(d3); Console.ReadLine(); } } |
检查是否正在从float转换为double,这可能导致此问题。