c#:两个双数字的总和问题

可能重复:
为什么C#中的浮点运算不精确?

你好。 我有以下问题:

43.65+61.11=104.75999999999999 

对于十进制是正确的:

 (decimal)43.65+(decimal)61.11=104.76 

为什么双重结果是错误的?

这个问题及其答案是关于此的丰富信息 – 在.NET中十进制,浮点数和双精度之间的差异?

报价:

  • 对于“自然精确小数”的值,最好使用小数。 这通常适用于人类发明的任何概念:财务价值是最明显的例子,但也有其他概念。 例如,考虑给予潜水员或滑冰者的分数。

  • 对于无论如何都无法真正精确测量的更多人工制品的值,浮动/双重更合适。 例如,科学数据通常以这种forms表示。 在这里,原始值不会以“十进制精度”开头,因此保持“十进制精度”对于预期结果并不重要。 使用浮点二进制点类型比使用小数要快得多。

简短回答:浮点表示(例如“双”)本质上是不准确的。 固定点也是如此(例如“十进制”),但定点表示的不准确性是另一种类型。 这是一个简短的解释: http : //effbot.org/pyfaq/why-are-floating-point-calculations-so-inaccurate.htm

您可以谷歌搜索“浮点不准确”或更多。

它归结为浮点数存储为二进制浮点数,并且与基数10一样,有一些数字在没有截断的情况下无法存储。 例如,基数为10的1/3,即.3重复出现。 转换为二进制时,您正在处理的数字是重复出现的。

我不同意浮点或双精度比十进制表示更准确或更准确。 它们与您选择精确度一样准确。 然而,它们是不同的表示,并且可以表示不同于基数10的数字。

十进制在基数10中存储数字。这可能会给你预期的结果

这不完全是错的。 它是由求和产生的二进制浮点数的最接近的十进制表示。

问题是由于使用二进制尾数,IEEE浮点数不能精确地表示43.65 + 61.11。 某些系统(例如Python 2.7和Visual C ++的标准I / O库)将舍入到解析为相同二进制的最简单小数,并将打印预期的104.76。 但是所有这些系统内部都得到完全相同的答案。

有趣的是,十进制表示法可以有限地表示任何有限二进制分数,而相反的情况则不成立。 如果人类有两个手指和计算机使用十状态记忆,我们就不会有这个问题。 🙂

因为double使用分数模型。 任何数字<1以x / y的形式表示。 鉴于该信息,一些数字只能近似。 对于高精度计算,请使用decimal,而不是double。

在这里看一些轻读:)

十进制算术非常适合数字的基数为10的表示,因为基数为10的数字可以用十进制精确表示。 (这就是为什么货币总是存储在货币适当的类中,或者存储在int并使用比例因子来表示’便士’或’便士’或其他类似的十进制货币。)

IEEE-754二进制数无法准确计算.1.01 。 因此,浮点格式接近输入,并且您可以获得近似输出,这对于浮点设计要处理的内容是完全可以接受 – 物理模拟,科学数据和快速数值数学方法。

注意这个简单的程序和输出:

 #include  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\n", g, e, m); return 0; } $ ./fp 0.0100000007078051567077636718750000000000, 0.0100000000000000019428902930940239457414, 0.0100000000000000011102569059430467124372 

所有这三种可能性都没有给出确切的答案, 0.01 ,但它们确实给出了非常接近答案的数字。

但是使用十进制算术作为货币。

真? 以下代码按预期返回104.76

 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

 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可能导致此问题。