关于c#:减去双打时的奇怪结果

Weird outcome when subtracting doubles

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
Why is floating point arithmetic in C# imprecise?

我一直在处理一些数字和C,下面的代码行会产生一个不同于预期的数字:

1
double num = (3600.2 - 3600.0);

我期望num为0.2,但结果却是0.19999999998181。是否有任何理由产生一个接近但仍然不同的小数?


这是因为double是浮点数据类型。

如果你想要更高的精度,你可以改用decimal

decimal的字面后缀是m,因此要使用decimal算术(并生成decimal结果),可以将代码编写为

1
var num = (3600.2m - 3600.0m);

注意,使用decimal有缺点。它是一个128位数据类型,而64位数据类型的大小与double的大小不同。这使得它在内存和处理方面都更加昂贵。它的范围也比double小得多。


这是有原因的。

原因是,在双数据类型的情况下,数字存储在内存中的方式不允许对数字3600.2进行精确表示。它也不允许数字0.2的精确表示。

0.2的二进制表示是无限的。如果要将它存储在内存或处理器寄存器中,为了执行一些计算,将存储一些接近0.2的有限表示数。如果您运行这样的代码,可能不太明显。

1
double num = (0.2 - 0.0);

这是因为在这种情况下,所有可用于表示双数据类型中数字的二进制数字都用于表示数字的小数部分(只有小数部分),并且精度更高。如果将数字3600.2存储在double类型的对象中,则某些数字用于表示整数部分-3600,而表示小数部分的数字较少。精度较低,事实上存储在内存中的分数部分与0.2的差别足够大,在从双精度转换为字符串后,它变得明显。


将您的类型改为decimal

1
decimal num = (3600.2m - 3600.0m);

你也应该读这个。


见维基百科

无法更好地解释。我也可以建议阅读每一个计算机科学家应该知道的关于浮点运算的知识。或者参阅stackoverflow的相关问题。