gpt4 book ai didi

javascript - Node.js 最大安全 float

转载 作者:行者123 更新时间:2023-11-30 09:31:29 26 4
gpt4 key购买 nike

在 Node.js 中,是否有像 Number.MAX_SAFE_INTEGER 这样的最大安全 float ?

我做了一个小实验来找出我可以用来从中减去 0.13 的(近似)数字:

console.log(Math.floor(Number.MAX_SAFE_INTEGER));  // 9007199254740991
console.log(Math.floor(Number.MAX_SAFE_INTEGER)-0.13); // 9007199254740991

console.log(Math.floor(Number.MAX_SAFE_INTEGER/2)); // 4503599627370495
console.log(Math.floor(Number.MAX_SAFE_INTEGER/2)-0.13); // 4503599627370495

console.log(Math.floor(Number.MAX_SAFE_INTEGER/4)); // 2251799813685247
console.log(Math.floor(Number.MAX_SAFE_INTEGER/4)-0.13); // 2251799813685246.8

console.log(Math.floor(Number.MAX_SAFE_INTEGER/64)); // 140737488355327
console.log(Math.floor(Number.MAX_SAFE_INTEGER/64)-0.13); // 140737488355326.88

console.log(Math.floor(Number.MAX_SAFE_INTEGER/128)); // 70368744177663
console.log(Math.floor(Number.MAX_SAFE_INTEGER/128)-0.13); // 70368744177662.87

我的猜测是随着目标精度的增加,最大值会降低。

最佳答案

对于 1 位小数的精度,您可以使用的最大数字是 562949953421311

精确到 2 位小数,它是 70368744177663。有趣的是,第一个数字等于:

(Number.MAX_SAFE_INTEGER + 1) / 16 - 1

第二个数字等于:

(Number.MAX_SAFE_INTEGER + 1) / 128 - 1

我们正在寻找的,是支持小数点后 d 位精度的最大安全数字。“支持”是指“可以可靠地进行基本算术运算”。

例如,我们知道 Number.MAX_SAFE_INTEGER(又名 2**53-1)安全的,因为基本算术被破坏了:

Number.MAX_SAFE_INTEGER - 0.1 === Number.MAX_SAFE_INTEGER
>>> true // unsafe

而且我们知道 0 安全的,因为:

0 + 0.1 === 0
>>> false // safe

顺便说一句,就 1e-323(包括)而言,0 是可靠的:

0 + 1e-323 === 0
>>> false // safe

0 + 1e-324 === 0
>>> true // unsafe

我在 0 和 Number.MAX_SAFE_INTEGER 之间进行二进制搜索,寻找满足该定义的最大数字,并得出这些数字。

这是代码(将任何其他数字传递给代码段末尾的 findMaxSafeFloat())

/**Returns whether basic arithmetic breaks between n and n+1, to a precision of `digits` after the decimal point*/
function isUnsafe(n, digits) {
// digits = 1 loops 10 times with 0.1 increases.
// digits = 2 means 100 steps of 0.01, and so on.
let prev = n;
for (let i = 10 ** -digits; i < 1; i += 10 ** -digits) {
if (n + i === prev) { // eg 10.2 === 10.1
return true;
}
prev = n + i;
}
return false;


}

/**Binary search between 0 and Number.MAX_SAFE_INTEGER (2**53 - 1) for the biggest number that is safe to the `digits` level of precision.
* digits=9 took ~30s, I wouldn't pass anything bigger.*/
function findMaxSafeFloat(digits, log = false) {
let n = Number.MAX_SAFE_INTEGER;
let lastSafe = 0;
let lastUnsafe = undefined;
while (true) {
if (log) {
console.table({
'': {
n,
'Relative to Number.MAX_SAFE_INTEGER': `(MAX + 1) / ${(Number.MAX_SAFE_INTEGER + 1) / (n + 1)} - 1`,
lastSafe,
lastUnsafe,
'lastUnsafe - lastSafe': lastUnsafe - lastSafe
}
});
}
if (isUnsafe(n, digits)) {
lastUnsafe = n;
} else { // safe
if (lastSafe + 1 === n) { // Closed in as far as possible
console.log(`\n\nMax safe number to a precision of ${digits} digits after the decimal point: ${n}\t((MAX + 1) / ${(Number.MAX_SAFE_INTEGER + 1) / (n + 1)} - 1)\n\n`);
return n;
} else {
lastSafe = n;
}
}
n = Math.round((lastSafe + lastUnsafe) / 2);
}
}

console.log(findMaxSafeFloat(1));

我通过排列安全数字发现的一件有趣的事情是,指数并没有以一致的方式上升。看下表;偶尔,指数增加(或减少)4,而不是 3。不知道为什么。

| Precision | First UNsafe                | 2^53/x                   |
|-----------|-----------------------------|--------------------------|
| 1 | 5,629,499,534,21,312 = 2^49 | x = 16 = 2^4 |
| 2 | 703,687,441,77,664 = 2^46 | x = 128 = 2^7 |
| 3 | 87,960,930,22,208 = 2^43 | x = 1,024 = 2^10 |
| 4 | 5,497,558,13,888 = 2^39 | x = 16,384 = 2^14 |
| 5 | 68,719,476,736 = 2^36 | x = 131,072 = 2^17 |
| 6 | 8,589,934,592 = 2^33 | x = 1,048,576 = 2^20 |
| 7 | 536,870,912 = 2^29 | x = 16,777,216 = 2^24 |
| 8 | 67,108,864 = 2^26 | x = 134,217,728 = 2^27 |
| 9 | 8,388,608 = 2^23 | x = 1,073,741,824 = 2^30 |

关于javascript - Node.js 最大安全 float ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45929493/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com