1

我最近发现了一个奇怪的 JS 片段,但是我不确定它是一个错误还是有一些逻辑。

试试这个数字:9000000022903136* 8 * 提醒它,控制台记录它,将它分配给一个变量。您将获得值 9000000022903136* 0 *。问题是为什么?它是一个错误吗?

我还注意到,您从 90000000229031352 到 90000000229031368 得到 90000000229031360,对于 90000000229031351,您得到 90000000229031340,对于 9000000022060313629,您得到 90109。

这发生在:Chrome、FF、Node.js

4

2 回答 2

3

Well, numbers in computers are limited (mostly). What you see here is the classic overflow of a floaty/doubly stored number, which can hold a number of digits, and the exponent of it, for instance (the actual implementation differs, of course):

123 is stored as [1 2 3], exponent 2. 1.23 is stored as [1 2 3], exponent 0.

So, 90000000229031368 is stored as:

[9 0 0 0 0 0 0 0 2 2 9 0 3 1 3 6], exponent 16. And as you can see, there is no more room for the last 8 digit, so it is set when you read it.

The other examples might seem contradictory, but keep in mind that the computer does not store those digits in base 10, but base 2.

Read more on this subject with the keywords: Float floating-point (e.g. on Wikipedia).

于 2013-10-23T05:45:36.173 回答
3

那是因为 javascript 数字是 64 位浮点数。

浮点数有 2 个部分 - 定义数字“值”的小数部分和定义数字应向小数点左侧或右侧移动多远的指数部分。

为了说明这项工作是如何工作的,我将使用基于十进制而不是二进制的虚构浮点数格式:

让我们将我们的想象格式定义为 8 个字符浮点数 - 即数字必须存储在 8 个字符内。让我们将格式划分为 6 个字符作为小数部分,2 个字符作为指数:

   _ _ _ _ _ _ _ _
  |_ _|_ _ _ _ _ _|  <--- 8 char float
exponent   fractional

为了便于讨论,让我们发明一种语法来描述格式:

exponent,fractional

例如,数字128可以存储为0,128,PI 可以存储为-5,314159(小数点左移 5 位)。

上面的 PI 案例是程序员第一次遇到浮点数的方式——他们需要使用小数而不是简单的整数。但浮点格式还有另一个特点——它可以存储比为小数部分分配的空间更大的数字!

例如,如果我们想以我们想象的 8char 浮点格式存储数字 987654321 怎么办?超过6个字符!好吧,我们会这样做:2,9876543. 也就是说,我们存储最高有效数字并将小数点向右移动 2 个空格。

如果我们尝试读取该数字,则得到的是 987654300。我们丢失了最低有效数字!嗯..听起来很熟悉。

对于 javascript,格式为 IEEE 754 64 位二进制浮点数。它为小数部分分配了 52 位(如果包括符号位,则为 53)。这意味着对于最多 52 位的数字,它的行为就像一个整数。任何更大,它将开始牺牲最低有效位(不是数字,位,因此舍入对我们人类来说可能看起来很奇怪)。

有关 64 位浮点数如何工作的更多详细信息,请参阅此维基百科文章:http ://en.wikipedia.org/wiki/Double_precision_floating-point_format

于 2013-10-23T06:03:09.783 回答