提问人:wcminipgasker2023 提问时间:10/13/2023 最后编辑:wcminipgasker2023 更新时间:11/14/2023 访问量:87
没有溢流和下溢,对于浮点数 x,x/4 是否总是等于 x/2/2(对于 x*4 == x*2*2)?
Without overflow and underflow, for a float number x, is x/4 always equals to x/2/2 (also for x*4 == x*2*2)?
问:
例如,据我所知,一个浮点 x,其 x/n^2 可能不等于 x/n/n,因为在 x/n/n 中,这将首先创建一个中间 x/n。例如:
document.write(1.23456789/49 == 1.23456789/7/7);
但是,如果没有溢出和下溢,x/4 == x/2/2 是否为例外,这始终是正确的?
我测试了:
document.write(1.23456789/4 == 1.23456789/2/2);
同样对于二进制文件:
1.23456789 的二进制(实际浮点数:1.2345678806304931640625):
0 01111111 00111100000011001010010
0.61728394031524658203125 的二进制文件 (1.2345678806304931640625/2)
0 10000000 00111100000011001010010
当乘法仅改变“指数”部分(01111111到 10000000)时,似乎只改变分数部分(00111100000011001010010)。
所以目前我有一个“假设”:对于没有溢出和下溢的浮点数 x,x/4 应该始终等于 x/2/2,对于 x * 4==x * 2 * 2,这是真的吗?
答:
我以为只有 2 的幂才是正确的。所以我尝试了你的浮点数和其他质数,发现它显然只对 7?,所以决定暴力破解它。
function testEqualityForRandomNumbers(iterations, f) {
let equalCount = 0;
const failedTests = [];
for (let a = 1; a <= iterations; a++) {
const leftSide = (f / a) / a;
const rightSide = f / (a * a);
if (leftSide == rightSide) {
equalCount++;
} else {
failedTests.push(a);
}
}
return failedTests;
}
function removeFailedTests(digits, digitsToRemove) {
let allDigits = Array.from({ length: digits }, (_, i) => i + 1);
for (let i = 0; i < 10000; i++) {
const f = Math.random() + 1;
const failedTests = testEqualityForRandomNumbers(digits, f);
// Remove the digits that have failed the test
allDigits = allDigits.filter((digit) => !failedTests.includes(digit));
// If no more digits are left, stop the process
if (allDigits.length === 0) {
console.log('All digits have failed the test.');
break;
}
}
console.log(allDigits)
}
const digits = 10000;
removeFailedTests(digits);
[1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, 8192]
对于随机浮点数,是的,只有 2 的指数存活。但在这一点上,我对 7 和你的 1.23456 更好奇......
如果没有上溢和下溢,由于基数是 2,因此乘以 2 的幂和除法始终是精确运算。由于这里不涉及四舍五入,因此等于 和 等于 ,因为在实数上也是如此。x/4
x/2/2
x*4
x*2*2
请注意,如果为 ±0,则两个表达式的结果符号将相同。x
编辑:更一般地说,在每个表达式中,您可能有一个非 2 幂的数字的乘法或除法。例如,和 总是等于 。x/2/3
x/3/2
x/6
没有溢流和下溢,对于浮点数 x,x/4 是否总是等于 x/2/2(也适用于 x4 == x2*2)?
这在 JavaScript 使用的浮点格式中是正确的,但在通常的浮点格式中却不是这样。
有限浮点数表示为 ±f•be,其中:
- b 是格式的固定基础。
- p(下面用)是格式的精度,位数。
- f 是一个整数,以 b 为基数的 p 位。
- e 是 e min ≤ e ≤ e max 范围内的整数,对于某些 e min 和 e max,它们是格式的固定限制。
(浮点格式通常也用 f 在其第一个数字之前或之后有一个基点来描述,因此它并不总是一个整数,并且位于诸如 [1, b[ 或 [1/b, 1[.但是,指数限制会相应地调整,并且这些描述在数学上是等效的。将 f 缩放为整数对于浮点属性的数论证明很有用。
浮点运算产生的结果就好像根据某种舍入规则将相应的实数运算的结果四舍五入到最接近的可表示数一样,最常见的是四舍五入到最接近的,与具有偶数低位数的可表示数(或者,如果两者都没有偶数低,则大值)。
JavaScript 使用二进制格式(b 为 2)。使用二进制格式时,±f•b e 除以 4 的实数结果为 ±f•be−2。由于给定我们没有下溢,因此 e−2 在从 e min 到 emax 的范围内,因此 ±f•be−2 可以用格式表示,因此它是可用于实数结果的壁橱,因此它是浮点除以 4 产生的结果。同样,除以 2 的实数结果是 ±f•be−1,它是可表示的,因此它是浮点除法的结果。然后将其除以 2 得到 ±f•be−2。因此,我们看到将任何可表示的有限数除以 4 的结果等于将其除以 2 两次的结果。(我们还可以检查这是否适用于有限数以外的事物;它适用于±∞和NaN。
但是,某些软件使用其他浮点格式。考虑以 p = 3 为基数 10,取可表示数 +345•100。在这种格式中,除以 4 的实数结果为 +86.25•100 = +862.5•10−1,因此浮点结果是最接近的可表示值 +862•10−1。当我们除以 +345•100.乘以 2,实数结果为 172.5•100。在这里,172•10 0 和 173•10 0 同样接近,因此浮点结果是偶数低位 172•100 的结果。当我们将其除以 2 时,实数结果是 86•100,这是可表示的,所以它是浮点结果。
因此,使用三位数以十为基数的格式,产生 86.2,但产生 86。345/4
345/2/2
评论
x/2