Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/436.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 32位整数乘法模拟_Javascript - Fatal编程技术网

javascript 32位整数乘法模拟

javascript 32位整数乘法模拟,javascript,Javascript,我只想乘以int,就像32位整数一样,带溢出 有些文章很容易喜欢按位操作 function add32bit( a, b ) { return (a+b)|0; } 就这样 function mul32bit( a, b ) { return (a*b)|0; } 但这不是工作 在32位整数系统中,允许整数溢出 计算 12312311 * 1231231211 = -236858179 但是使用javascript (12312311 * 1231231211)|0 = -

我只想乘以int,就像32位整数一样,带溢出

有些文章很容易喜欢按位操作

function add32bit( a, b )
{
    return (a+b)|0;
}
就这样

function mul32bit( a, b )
{
    return (a*b)|0;
}
但这不是工作

在32位整数系统中,允许整数溢出

计算

12312311 * 1231231211 = -236858179
但是使用javascript

(12312311 * 1231231211)|0 = -236858180
有一种方法可以精确计算。

解决方案(?) 根据Richie Frame的提示,我尝试使用编写一个函数,将两个整数相乘,并将结果作为有符号32位整数返回

// base algorithm from: https://en.wikipedia.org/wiki/Karatsuba_algorithm
// modified to discard values unneccessary for 32-Bit-operations

function int32_mul(x, y)
{
    // We use B = 2 and m = 16, because it will make sure that we only do multiplications with
    // 16 Bit per factor so that the result must have less than 32 Bit in total (which fits well
    // into a double).
    var bm = 1 << 16;

    x0 = x % bm;
    x1 = (x - x0) / bm;

    y0 = y % bm;
    y1 = (y - y0) / bm;

    // z1 + z0. We can discard z2 completely as it only contains a value out of our relevant bounds.
    // Both z1 and z0 are 32 Bit, but we shift out the top 16 Bit of z1.
    return (((x1 * y0 + x0 * y1) << 16) + (x0 * y0)) | 0;
}
Javascript对所有计算(甚至是整数计算)使用双精度。通过以上测试,我得出结论,double不能具有
15159301582738621
的值

这是因为浮点数据类型(如float(32位)、double(64位)和quad(128位)是如何工作的。基本上,它们不存储精确的值,而是以
x*2^y
的形式存储值的
x
y
值,这使它们能够存储非常大的值和非常小的值。我们(人类)过去对于非常大的数字和非常小的数字都有类似的语法,例如十亿的
1e9
,或者
1e-5
0.00001
,而
e
*10^
的快捷方式

现在假设您计算
10001*10001
,这显然是
100020001
,但假设您只能存储5位数字和一个指数。要存储结果,您必须对其进行近似,并使用例如
1.0002e8
10002e4
。正如你所看到的,你必须忘记最后的1。事实上,你的例子中双倍的问题非常相似,只是规模更大,基数是2,而不是10


最后两个
printf
语句证明double不能保存值
15159301582738621
,这是示例计算的精确结果。如果您尝试使用
12312311*1231231212
(第二个数字的末尾是2,而不是1),您会发现并非此范围内的所有数字都不能存储为双精度,因为该计算方法可以很好地用于您的函数。

能否显示将传递给函数的值以及预期的结果?请出示你要找的Karatsuba乘法
var tests = [
    [ 0, 0, 0 ],
    [ 0, 1, 0 ],
    [ 1, 1 << 8, 256 ],
    [ 1, 1 << 16, 65536 ],
    [ 1, 1 << 24, 16777216 ],
    [ 1, 0x7fffffff, 2147483647 ],
    [ 1, 0x80000000, -2147483648 ],
    [ 1, 0xffffffff, -1 ],
    [ 2, 1 << 8, 512 ],
    [ 2, 1 << 16, 131072 ],
    [ 2, 1 << 24, 33554432 ],
    [ 2, 0x80000000, 0 ],
    [ 2, 0x7fffffff, -2 ],
    [ 2, 0xffffffff, -2 ],
    [ 256, 256, 65536 ],
    [ 65536, 65536, 0 ],
    [ -2, 2, -4 ],
    [ -65536, 65536, 0 ],
    [ -2, -2, 4 ],
    [ -2147483648, 1, -2147483648 ],
    [ -2147483649, 1, 2147483647 ],
    [ 12312311, 1231231211, -236858179 ],
];

for (var i = 0; i < tests.length; ++i)
{
    var test = tests[i];
    if (int32_mul(test[0], test[1]) !== test[2])
    { console.log(test[0], '*', test[1], '!==', test[2]); }
}
#include <stdio.h>
#include <stdint.h>

int main(void) {
    printf("%d\n", (int32_t)(12312311L * 1231231211L));
    printf("%llu\n", (uint64_t)12312311L * 1231231211L);
    printf("%.32f\n", 12312311. * 1231231211.);
    printf("%.8f\n", 15159301582738621.);
    return 0;
}
-236858179
15159301582738621
15159301582738620.00000000000000000000000000000000
15159301582738620.00000000