yes*_*aaj 46 floating-point precision
double r = 11.631;
double theta = 21.4;
Run Code Online (Sandbox Code Playgroud)
在调试器中,这些显示为11.631000000000000和21.399999618530273.
我怎么能避免这个?
Jef*_*ood 38
我喜欢Joel的解释,它解决了Excel 2007中类似的二进制浮点精度问题:
看看最后那里有很多0110 0110 0110?这是因为0.1具有二进制没有确切的表示 ......这是一个循环二进制数.这有点像1/3没有十进制表示.1/3是0.33333333,你必须永远写3.如果你失去耐心,你会得到一些不准确的东西.
所以你可以想象一下,如果你试图做3*1/3,并且你没有时间永远写3,你会得到的结果是0.99999999,而不是1,人们会生气你错了.
Mar*_*ram 11
如果你有一个像这样的值:
double theta = 21.4;
Run Code Online (Sandbox Code Playgroud)
而且你想做:
if (theta == 21.4)
{
}
Run Code Online (Sandbox Code Playgroud)
你必须要有点聪明,你需要检查theta的值是否真的接近21.4,但不一定是那个值.
if (fabs(theta - 21.4) <= 1e-6)
{
}
Run Code Online (Sandbox Code Playgroud)
这部分是针对特定平台的 - 我们不知道您正在使用什么平台.
这也部分是知道你真正想要看到的东西.调试器正在向您展示 - 无论如何 - 存储在变量中的精确值.在我关于.NET中二进制浮点数的文章中,有一个C#类可以让你看到存储在double中的绝对精确数字.目前在线版本尚未正常工作 - 我会尝试将其中一个放在另一个网站上.
鉴于调试器看到"实际"值,它必须对要显示的内容进行判断调用 - 它可以显示舍入到几个小数位的值,或更精确的值.有些调试器在阅读开发人员的头脑方面比其他调试器做得更好,但这是二进制浮点数的基本问题.
decimal如果想要在精度极限下保持稳定性,请使用定点类型.有开销,如果您希望转换为浮点,则必须显式转换.如果你确实转换为浮点数,你将重新引入似乎困扰你的不稳定性.
或者,您可以克服它并学习使用浮点运算的有限精度.例如,您可以使用舍入来使值收敛,或者您可以使用epsilon比较来描述容差."Epsilon"是您设置的常量,用于定义容差.例如,如果两个值在0.0001之间,则可以选择将它们视为相等.
我发现你可以使用运算符重载来使epsilon比较透明.那会非常酷.
对于尾数指数表示,必须计算EPSILON以保持在可表示的精度内.对于数字N,Epsilon = N/10E + 14
System.Double.Epsilon是该Double类型的最小可表示正值.它对我们来说太小了.阅读微软关于平等测试的建议