Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/416.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaScript中错误舍入的大量数字_Javascript_Floating Point_Floating Accuracy_Ieee 754 - Fatal编程技术网

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 有关详细信息,请参阅此博客文章: JavaScript的数字类型的容量已满,有关详细

请参阅此代码:

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

log(jsonString,jsonParsed)它不是由此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更高的精度


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

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

JavaScript使用双精度浮点值,即总精度为53位,但您需要

ceil(lb 714341252076979033) = 60
位来精确表示值

最近的可精确表示的数字是
714341252076979072
(将原始数字写成二进制,将最后7位数字替换为
0
,并向上取整,因为替换的最高数字是
1


您将得到
714341252076979100
而不是这个数字,因为ECMA-262描述的
ToString()
,§9.8.1以10的幂次运算,在53位精度下,所有这些数字都是相等的。

JavaScript只能处理高达约9亿的精确整数(即9加15个零)。比这还高,你就会得到垃圾。通过使用字符串保存数字来解决这个问题。如果你需要用这些数字做数学运算,写下你自己的函数,或者看看你是否能找到它们的库:我建议使用前者,因为我不喜欢我见过的库。要开始学习,请参阅我的两个函数。

感谢大家提供快速有用的答案,我希望我能将这三个函数都标记为正式答案。感谢链接到我的文章,但它只解释了一半的问题——打印内部舍入值。即使javascript允许您打印整个内容,它仍然是错误的——它将是最接近的可表示双精度值,正如下面其他人所解释的。我喜欢这个答案,因为它实际上告诉你如何解决这个问题。这是一个奇妙的答案,也是我一直在寻找的答案。15位有效的十进制数字“1434112520769791”而不是“714341252076979”是我不理解的。这个答案似乎有两个错误:1)轻微,最后一个数字缺少前导
7
,2)主调,输出未四舍五入到15位——它也是53位尾数浮点的最接近表示形式,约占15.95位小数。
..100
部分不如四舍五入稳定,例如
..79135
错误进入
..79100
..79136
错误进入
..79200
,甚至这个
..35
//code>..36
极限也会任意漂移。(学究式模式:在某种意义上,它是四舍五入,因为它“四舍五入”到15.95位小数)