为什么Chrome在(.1).toString(3)的点后产生1099位数?

GOT*_*O 0 5 javascript floating-point google-chrome base tostring

我有一种感觉,这只是一个无害的bug,但我仍然想知道发生了什么.

我正在玩一些代码来在画布上渲染Peano曲线,当我注意到一个函数在Chrome中返回荒谬的长字符串时,该画布涉及在基数3中表达逻辑坐标.更仔细地看,事实证明了这个表达方式

(.1).toString(3)
Run Code Online (Sandbox Code Playgroud)

在Chrome中评估

0.

如下所示:http://jsfiddle.net/zvp8osm8/

据我所知,在这种情况下,只有点后面的前33位有意义,其余的看起来像没有可识别模式的随机垃圾.用点后,1099(!)的数字相似的结果产生了不同的基础和指数过于喜欢(10000000000.1).toString(3)(.7).toString(7).其他值(.5).toString(3)也会产生很长的字符串,但数字都有意义.

除Opera之外的其他浏览器在每种情况下只产生合理数量的数字,这使我认为问题出在Chrome的Javascript引擎中.

我现在有两个问题:

  • 为什么基数3中的十进制数字表示在Chrome中包含这么多无关紧要的数字?
  • 随机数字可能来自哪里?

Mar*_*son 5

对于您显示的特定情况,看起来好像是使用以下天真算法生成数字,从x = .1.

  1. 乘以x3.
  2. 提取结果的整数和小数部分.
  3. 将整数部分输出为数字,并x用小数部分替换.
  4. 重复步骤1到3直到无聊(或直到达到某个预设限制).

这在数学上可以很好地工作,但是在浮点世界中,这当然是完全无稽之谈,因为乘以3和随后的舍入到最近的浮点数可能会引入一个小的错误,并且在30位左右之后错误已经完全淹没了原始数字,我们只是变得垃圾.

据推测,在初始数大于1.0绝对值的情况下,还有一些处理点之前的数字的方法,但没有样本输出,我不会猜测算法是什么.

为了证明上述原因,这里有一些Python中的代码,其输出与问题中给出的完全匹配.这里modf是提取Python float的小数部分和整数部分的操作.

>>> from math import modf
>>> x = 0.1
>>> digits = []
>>> for _ in xrange(1099):
...     x, digit = modf(3.0 * x)
...     digits.append(str(int(digit)))
... 
>>> print('0.' + ''.join(digits))
Run Code Online (Sandbox Code Playgroud)

并输出:

0.

这应该回答你的一个问题:即随机数字的来源.我无法回答为什么Chrome选择输出这么多数字的问题.