double r = 11.631;
double theta = 21.4;
在调试器中,它们显示为
11.631000000000000
和21.399999618530273
。我应该如何避免这种情况?
double r = 11.631;
double theta = 21.4;
11.631000000000000
和21.399999618530273
。我喜欢 Joel 的解释,它涉及到Excel 2007中的类似二进制浮点精度问题:
看那里有很多0110 0110 0110吗?这是因为0.1在二进制中没有精确的表示... 它是一个重复的二进制数。这有点像1/3在十进制中没有表示法。1/3是0.33333333,你必须一直写3。如果你失去耐心,你会得到不精确的结果。
所以你可以想象,在十进制中,如果你尝试做3*1/3,而且你没有时间一直写3,你得到的结果将是0.99999999,而不是1,人们会因为你错误而生气。
*
或 /
运算符优先级更高。 - Peter Olson如果您有这样的值:
double theta = 21.4;
而你想要做的是:
if (theta == 21.4)
{
}
你需要有一些才智,你需要检查theta的值是否真正地接近21.4,但不一定要等于那个值。
if (fabs(theta - 21.4) <= 1e-6)
{
}
decimal
类型,如果你想在精度极限处获得稳定性。这会增加开销,并且如果需要转换为浮点数,则必须显式地进行强制转换。如果您转换为浮点数,则会重新引入似乎困扰您的不稳定性。System.Double.Epsilon
是Double
类型的最小可表示正值。它对我们来说太小了。请阅读Microsoft关于相等性测试的建议。但实际上它们是基于二进制的:1.1相当于11 x 10^-1
你无法避免它,你只能逐渐适应某些浮点数是“无理”的事实,就像1/3一样。1.1相当于154811237190861 x 2 ^-47
您可以避免这种情况的一种方法是使用一个使用另一种表示十进制数的库,例如BCD
。该方法可以防止浮点数精度问题。如果您正在使用Java并且需要准确性,请使用BigDecimal类进行浮点数计算。它的速度会比较慢,但更加安全。
在我看来,21.399999618530273是对21.4的单精度(float)表示。看起来调试器在某处将双精度转换为单精度。