Floating point 为什么我看到一个初始化为21.4这样的值的双变量是21.3999618530273? double r=11.631; 双θ=21.4;

Floating point 为什么我看到一个初始化为21.4这样的值的双变量是21.3999618530273? double r=11.631; 双θ=21.4;,floating-point,precision,Floating Point,Precision,在调试器中,它们显示为11.6310000000000和21.399999618530273 如何避免这种情况?这是由于浮点数的数量太多造成的,您没有什么办法可以避免它 顺便说一下,在运行时打印这些值通常会导致正确的结果,至少使用现代C++编译器。对于大多数操作,这不是什么大问题。如果您有如下值: double theta=21.4; 你要做的是: if(θ=21.4) { } 你必须聪明一点,你需要检查θ的值是否真的接近21.4,但不一定是这个值 if(fabs(θ-21.4)避免这种情况

在调试器中,它们显示为
11.6310000000000
21.399999618530273

如何避免这种情况?

这是由于浮点数的数量太多造成的,您没有什么办法可以避免它


顺便说一下,在运行时打印这些值通常会导致正确的结果,至少使用现代C++编译器。对于大多数操作,这不是什么大问题。

如果您有如下值:

double theta=21.4;
你要做的是:

if(θ=21.4)
{
}
你必须聪明一点,你需要检查θ的值是否真的接近21.4,但不一定是这个值


if(fabs(θ-21.4)避免这种情况的一种方法是使用一个库,该库使用另一种表示十进制数的方法,例如

如果您使用Java并且需要精度,请使用BigDecimal类进行浮点计算。它速度较慢但更安全。

我喜欢,它处理Excel 2中类似的二进制浮点精度问题007:

看看结尾有多少0110100110?那是因为0.1没有精确的二进制表示法…这是一个重复的二进制数。这有点像1/3没有十进制表示法。1/3是0.33333333,你必须永远写3。如果你失去耐心,你会得到一些不精确的结果

所以你可以想象,在十进制中,如果你尝试做3*1/3,而你没有时间永远写3,你得到的结果将是0.9999999,而不是1,人们会因为你的错误而生气


如果希望精度限制下的稳定性,请使用定点
decimal
类型。这会产生开销,如果希望转换为浮点,则必须显式强制转换。如果确实转换为浮点,则会重新引入似乎困扰您的不稳定性

或者,你可以克服它,学习使用浮点运算的有限精度。例如,你可以使用舍入使值收敛,或者你可以使用ε比较来描述公差。“ε”是您设置的定义公差的常数。例如,如果两个值之间的距离在0.0001范围内,您可以选择将它们视为相等

我突然想到,可以使用运算符重载使ε比较透明。那将非常酷


对于尾数指数表示法,必须计算EPSILON以保持在可表示精度内。对于数字N,EPSILON=N/10E+14


System.Double.Epsilon
Double
类型的最小可表示正值。它对于我们的目的来说太小了。请阅读这部分是特定于平台的-我们不知道您使用的是什么平台

这在一定程度上也是一种了解您实际想要看到什么的情况。调试器正在向您显示—无论如何,在某种程度上—存储在变量中的精确值。在我的示例中,有一个函数可以让您看到存储在double中的绝对精确数字。在线版本目前不起作用—我将尝试在另一个网站上发布一个


假设调试器看到“实际的”值,它必须对要显示的内容进行判断-它可以向您显示四舍五入到小数点后几位的值,或者更精确的值。有些调试器在理解开发人员的想法方面比其他调试器做得更好,但这是二进制浮点数的一个基本问题。

在我看来,21.39999618530273是一个p21.4的精度(浮点)表示。看起来调试器正在从double向下转换为float。

如果它困扰您,您可以自定义调试期间某些值的显示方式。请小心使用:-)


您无法避免这一点,因为您使用的是固定字节数的浮点数。实数和它的有限符号之间根本不可能有同构

但大多数时候你可以忽略它。21.4==21.4仍然是真的,因为它仍然是具有相同错误的相同数字。但是21.4f==21.4可能不是真的,因为float和double的误差不同


如果你需要固定精度,也许你应该试试固定点数。甚至是整数。例如,我经常使用int(1000*x)来传递到调试寻呼机。

我以前遇到过这个问题()-我认为令人惊讶的是“无理”数字是不同的

这里我所说的“非理性”只是指,它们不能用这种格式准确地表示出来。实数无理数(如π-pi)根本无法精确表示

大多数人都熟悉1/3不是十进制的:0.3333

奇怪的是1.1在浮动中不起作用。人们希望十进制值在浮点数中起作用,因为他们是如何看待它们的:

1.1是11 x 10^-1

当他们真的在二垒的时候

1.1是154811237190861 x 2^-47

你无法避免它,你只需要习惯一些浮点数是“非理性”的事实,就像1/3是一样


在比较浮动时也要注意,有关更多信息,请参阅。

根据javadoc

如果数字运算符的至少一个操作数为double类型,则 使用64位浮点运算执行操作,并且 数字运算符是double类型的值。如果另一个操作数不是double,则为
首先通过数字升级(§5.6)将(§5.1.5)加宽为双精度类型。“


有比BCD更好的技术。如果能说出其中的一两种技术,那就太好了。快记(但不是相反