尽管存在错误,为什么浮点文字表示为?

saw*_*awa 1 ruby floating-point literals

我的理解是浮点数在内部表示为二进制扩展,这会引入错误.如果是这种情况,那么为什么浮点文字表示为给出?假设在0.1内部表示为0.0999999999999999根据二进制扩展(我使用一个假的例子,只是为了表明这一点.这个特殊的值可能不正确.).然后在检查或irb的返回值中,为什么它/为什么可以打印给定的文字0.1而不是0.0999999999999999?一旦它被解释并扩展为二进制文件,原始文字形式是不是已经消失了?

换句话说,float literal-to-internal二进制表达式是多对一映射.足够接近的不同浮点文字将映射到相同的内部二进制表达式.那么,为什么有可能重建原始从内部表达字面(模数之间的差异1.101.1,1.23e2 123.0在马克·狄金森的评论)?

Pas*_*uoq 6

对于大多数平台,应用于浮点文字(如"0.1")的十进制到浮点转换将舍入到最接近的浮点(0.5 ULP).(Ruby为此调用了一个来自平台的函数,而Ruby的源代码中包含的唯一可靠性是可怕的,但让我们假设转换为最接近的).因此,如果您打印到1 ... 15之间的任意小数,则最接近的十进制表示形式与文字对应的double 0.1,则结果为0.10 ... 0(当然,可以省略尾随零),并且如果你打印最短的十进制表示转换回最接近的0.1,那么这当然会导致"0.1".

在将浮点数转换为十进制表示时,编程语言通常使用上述两种方法之一(固定数字的有效数字,或最短的十进制表示,转换回原始浮点数).Ruby使用后者.

本文介绍了"浮点到最短的十进制表示形式,它转换回相同的浮点数"浮点到十进制的转换.


Mar*_*son 5

Ruby(与其他几种语言,包括Java和Python一样)在将二进制浮点数转换为十进制时使用"最短字符串"表示用于显示目的:给定二进制浮点数,它将计算舍入的最短十进制字符串返回到通常的舍入到最接近的十进制到二进制方法下的二进制浮点数.

现在假设我们从一个相当短的(有效数字的数量)十进制文字开始,123.456例如,并将其转换为最接近的二进制浮点数,z.显然123.456一个十进制的十进制字符串z,因此它是表示的候选者z,并且它应该至少可以说"最短字符串"算法会向我们吐出.但是我们在这里不仅仅是合理性:确保这123.456正是我们要回来的,我们需要知道的是,没有其他更短的候选人.

这是真的,主要是因为如果我们限制为short-ish十进制值(在下面更加精确),连续的这些值之间的间隔大于连续浮点之间的间距.更准确地说,我们可以做出如下声明:

任何十进制文本x有15个或更少显著数字和绝对值之间10^-307,并10^308会通过"最短串"算法来恢复.

这里通过"恢复",我的意思是输出字符串将具有相同的十进制数字,并且当被认为是十进制数字时与原始文字相同的值; 它仍然有可能是文字的形式可能已经改变,例如,从1.2301.23,或者0.0003453.45e-4.我也假设IEEE 754 binary64格式具有通常的round-ties-to-even舍入模式.

现在让我们给出一个证明的草图.不失一般性,假设x是积极的.我们z是最接近的二进制浮点值x.我们必须表明,有没有其他,短,字符串,y舍入到z下一轮到最近.但是如果它y是一个比较短的字符串x,它也可以用15位有效数字表示,或者更少,所以它与x至少一个"最后一个单位"不同.为了形式化,找到整数ef那样的2^(e-1) <= x < 2^e10^(f-1) < x <= 10^f.然后差异|x-y|至少是10^(f-15).但是,如果y离得太远x,它就不可能舍入到z:因为binary64格式具有53位的精度(至少远离下溢和溢出范围),舍入的数字的间隔z最多为宽度2^(e-53)[1].我们需要证明这个区间的宽度小于|x-y|; 那就是那个2^(e-53) < 10^(f-15).

但是,这是从我们的选择:2^(e-53) <= 2^-52 x由我们选择的e,既然2^-52 < 10^-15我们得到2^(e-53) < 10^-15 x.然后10^-15 x <= 10^(f-15)(通过选择f).

15在这里找到最好的例子并不难.例如,文字8.123451234512346有16位有效数字,并转换为浮点值0x1.03f35000dc341p+3,或4573096494089025/562949953421312.当使用最短的字符串算法渲染回字符串时,我们得到8.123451234512347.


[1]不完全正确:当z一个精确的2的幂时,有一个烦人的角情况,在这种情况下,间隔的宽度是1.5 2^(e-53).但是,在这种情况下,该陈述仍然适用; 我会把细节留作练习.