考虑形式为d1.d2d3d4d5 ... dnExxx的十进制表示形式,其中xxx是任意指数,d1和dn都是非零。
是否已知最大n,使得存在十进制表示d1.d2d3d4d5 ... dnExxx使得间隔(d1.d2d3d4d5 ... dnExxx,d1.d2d3d4d5 ...((dn)+1)Exxx)包含一个IEEE 754双?
n应至少为17.问题是17岁以上。
这个数字n与小数到双倍转换(例如strtod()
)中足以考虑的位数有关。我查看了David M. Gay's implementation的源代码,希望在那里找到答案。有一个暗示“40”,但不清楚这是否是一个合理的数学结果或只是一个统计上安全的界限。此外,关于“截断”的注释使其听起来像0.50000000000000000000000000000000000000000000000000000001可以在向上舍入模式中转换为0.5。
Musl's implementation似乎读了大约125 * 9位数,这很多。然后它切换到“粘性”模式:
if (c!='0') x[KMAX-4] |= 1;
最后,当用“包含两个连续的IEEE 754双打的中点”替换“包含IEEE 754双”时,答案是如何改变的?
答案 0 :(得分:6)
当你有一个带有奇数有效数的次正规数,即2^(-1074)
的奇数倍时,你有一个数字,其十进制表示中的最后一个非零数字是1074 th 之后小数点。然后,您在小数点后面直接有大约300个零,因此该数字有大约750-770个有效十进制数字。最小的正次正规,2^(-1074)
有751位有效数字,最大的正次正规,(2^52-1)*2^(-1074)
有767位有效数字(我认为这是最大数字)。
因此,至少有一个十进制数字序列d1, ..., d766
,以便在开放区间内有一个IEEE754 double
(d1.d2...d766E-308, d1.d2...(d766 + 1)E-308)
如果我们考虑“包含两个连续的IEEE754 double
s的中点”,答案不会有太大变化,因为次正常double
s的有效小数位数大致相同,并且中点连续两次这样的。
在最坏的情况下,必须消耗整个数字序列(在最终1之前考虑"0.5000000...0001"
任意多个零,确定结果为0.5 + 0.5^53
而不是0.5
从零或向上四舍五入。)
然而,只有
floor(DBL_MANT_DIG * log 2 / log 10) + 2 = 17
区分不同double
值所需的有效十进制数字,因此一种相对容易(尽管可能不是非常有效)的解析方法是将第一个(至少17个)数字(和指数)解析为最接近的double
,并将输入字符串与该double
值(及其邻居)的确切表示进行比较。