JavaScript中错误舍入的大量数字

JavaScript中错误舍入的大量数字,javascript,floating-point,floating-accuracy,ieee-754,Javascript,Floating Point,Floating Accuracy,Ieee 754,请参阅此代码: var jsonString='{“id”:714341252076979033,“type”:“FUZZY”}; var jsonParsed=JSON.parse(jsonString); log(jsonString,jsonParsed)它不是由此json解析器引起的。只需尝试将714341252076979033输入fbug的控制台。您将看到相同的714341252076979100 有关详细信息,请参阅此博客文章: 这不是由此json解析器引起的。只需尝试将7143

请参阅此代码:

var jsonString='{“id”:714341252076979033,“type”:“FUZZY”};
var jsonParsed=JSON.parse(jsonString);

log(jsonString,jsonParsed)它不是由此json解析器引起的。只需尝试将714341252076979033输入fbug的控制台。您将看到相同的714341252076979100

有关详细信息,请参阅此博客文章:

这不是由此json解析器引起的。只需尝试将714341252076979033输入fbug的控制台。您将看到相同的714341252076979100

有关详细信息,请参阅此博客文章:

JavaScript的
数字类型的容量已满,有关详细信息,请参阅。这些ID必须是字符串

IEEE-754双精度浮点(JavaScript使用的那种数字)当然不能精确地表示所有的数字。众所周知,
0.1+0.2==0.3
是错误的。它可以影响整数,就像它影响分数一样;一旦超过9007199254740991(
Number.MAX\u SAFE\u INTEGER
),它就会启动

除了
Number.MAX_SAFE_INTEGER+1
9007199254740992
),IEEE-754浮点格式不能再表示每个连续整数
9007199254740991+1
9007199254740992
,但是
9007199254740992+1
也是
9007199254740992
,因为
9007199254740993
不能以该格式表示。下一个可以是
9007199254740994
。然后
9007199254740995
不能,但
9007199254740996
可以

原因是我们已经用完了位,所以我们不再有1s位;最低阶位现在表示2的倍数。最终,如果我们继续下去,我们会失去这一点,只能以4的倍数工作。等等

您的值远远高于该阈值,因此它们会四舍五入到最接近的可表示值

从ES2020开始,可以对任意大的整数使用,但没有JSON表示。您可以使用字符串和恢复器函数:

constjsonstring='{“id”:“714341252076979033”,“type”:“FUZZY”};
//注意,这是一个字符串−−−−^−−−−−−−−−−−−−−−−−−^
const obj=JSON.parse(jsonString,(键,值)=>{
if(key==“id”&&typeof value==“string”&&value.match(/^\d+$/){
返回BigInt(值);
}
返回值;
});
控制台日志(obj)

(查看真实控制台,snippets控制台不理解BigInt。)
您的JavaScript
数字类型的容量已经过大,有关详细信息,请参阅。这些ID必须是字符串

IEEE-754双精度浮点(JavaScript使用的那种数字)当然不能精确地表示所有的数字。众所周知,
0.1+0.2==0.3
是错误的。它可以影响整数,就像它影响分数一样;一旦超过9007199254740991(
Number.MAX\u SAFE\u INTEGER
),它就会启动

除了
Number.MAX_SAFE_INTEGER+1
9007199254740992
),IEEE-754浮点格式不能再表示每个连续整数
9007199254740991+1
9007199254740992
,但是
9007199254740992+1
也是
9007199254740992
,因为
9007199254740993
不能以该格式表示。下一个可以是
9007199254740994
。然后
9007199254740995
不能,但
9007199254740996
可以

原因是我们已经用完了位,所以我们不再有1s位;最低阶位现在表示2的倍数。最终,如果我们继续下去,我们会失去这一点,只能以4的倍数工作。等等

您的值远远高于该阈值,因此它们会四舍五入到最接近的可表示值

从ES2020开始,可以对任意大的整数使用,但没有JSON表示。您可以使用字符串和恢复器函数:

constjsonstring='{“id”:“714341252076979033”,“type”:“FUZZY”};
//注意,这是一个字符串−−−−^−−−−−−−−−−−−−−−−−−^
const obj=JSON.parse(jsonString,(键,值)=>{
if(key==“id”&&typeof value==“string”&&value.match(/^\d+$/){
返回BigInt(值);
}
返回值;
});
控制台日志(obj)

(看看真正的控制台,snippets控制台不理解BigInt。)
问题是您的数字需要比JavaScript更高的精度


你能以字符串的形式发送这个号码吗?分为两部分?

问题是您的数字需要比JavaScript更高的精度


你能以字符串的形式发送这个号码吗?分为两部分?

您在这里看到的实际上是两个圆角的效果。ECMAScript中的数字在内部表示为双精度浮点。当
id
设置为
714341252076979033
0x9e9d9958274c359
十六进制)时,它实际上被分配了最近的可表示双精度值,即
714341252076979072
0x9e9d9958274c380
)。当您打印出该值时,它被四舍五入到15位有效的十进制数字,这给出了
1434125207699100

您在这里看到的实际上是两次四舍五入的效果。ECMAScript中的数字在内部表示为双精度浮点。当
id
设置为
714341252076979033
0x9e9d9958274c359
十六进制)时,它实际上被分配了最近的可表示双精度值,即
714341252076979072
0x9e9d9958274c380
)。当您打印出该值时,它被四舍五入到15位有效的十进制数字,这将给出
1434125207699100

JavaSc
ceil(lb 714341252076979033) = 60