JavaScript summing large integers

旧时模样 提交于 2019-12-27 11:05:14

问题


In JavaScript I would like to create the binary hash of a large boolean array (54 elements) with the following method:

function bhash(arr) {
   for (var i = 0, L = arr.length, sum = 0; i < L; sum += Math.pow(2,i)*arr[i++]); 
   return sum;
}

In short: it creates the smallest integer to store an array of booleans in. Now my problem is that javascript apparently uses floats as default. The maximum number I have to create is 2^54-1 but once javascript reaches 2^53 it starts doing weird things:

9007199254740992+1 = 9007199254740994

Is there any way of using integers instead of floats in javascript? Or large integer summations?


回答1:


JavaScript uses floating point internally.

What is JavaScript's highest integer value that a number can go to without losing precision?

In other words you can't use more than 53 bits. In some implementations you may be limited to 31.

Try storing the bits in more than one variable, use a string, or get a bignum library, or if you only need to deal with integers, a biginteger library.




回答2:


javascript now has experimental support for BigInt.
At the time of writing only chrome supports this.

caniuse has no entry yet.

BigInt can be either used with a constructor, e.g. BigInt(20) or by appending n, e.g. 20n

Example:

const max = Number.MAX_SAFE_INTEGER;

console.log('javascript Number limit reached', max + 1 === max + 2) // true;

console.log('javascript BigInt limit reached', BigInt(max) + 1n === BigInt(max) + 2n); // false



回答3:


BigInt is being added as a native feature of JavaScript.

typeof 123;
// → 'number'
typeof 123n;
// → 'bigint'

Example:

const max = BigInt(Number.MAX_SAFE_INTEGER);
const two = 2n;
const result = max + two;
console.log(result);
// → '9007199254740993'



回答4:


Another implementation of large integer arithmetic (also using BigInt.js) is available at www.javascripter.net/math/calculators/100digitbigintcalculator.htm. Supports the operations + - * / as well as remainder, GCD, LCM, factorial, primality test, next prime, previous prime.




回答5:


There are various BigInteger Javascript libraries that you can find through googling. e.g. http://www.leemon.com/crypto/BigInt.html




回答6:


Here's (yet another) wrapper around Leemon Baird's BigInt.js

It is used in this online demo of a big integer calculator in JavaScript which implements the usual four operations + - * /, the modulus (%), and four builtin functions : the square root (sqrt), the power (pow), the recursive factorial (fact) and a memoizing Fibonacci (fibo).




回答7:


No. Javascript only has one numeric type. You've to code yourself or use a large integer library (and you cannot even overload arithmetic operators).

Update

This was true in 2010... now (2019) a BigInt library is being standardized and will most probably soon arrive natively in Javascript and it will be the second numeric type present (there are typed arrays, but - at least formally - values extracted from them are still double-precision floating point numbers).




回答8:


You're probably running into a byte length limit on your system. I'd take the array of booleans, convert it to an array of binary digits ([true, false, true] => [1,0,1]), then join this array into a string "101", then use parseInt('101',2), and you'll have your answer.




回答9:


So while attempting one of the leetcode problem I have written a function which takes two numbers in form of string and returns the sum of those numbers in form of string. (This doesn't work with negative numbers though we can modify this function to cover that)

var addTwoStr = function (s1, s2) {
s1 = s1.split("").reverse().join("")
s2 = s2.split("").reverse().join("")
var carry = 0, rS = '', x = null
if (s1.length > s2.length) {
    for (let i = 0; i < s1.length; i++) {
        let s = s1[i]
        if (i < s2.length) {
            x = Number(s) + Number(s2[i]) + carry
            rS += String((x % 10))
            carry = parseInt(x/10)
        } else {
            if (carry) {
                x = Number(s) + carry
                rS += String((x % 10))
                carry = parseInt(x/10)
            } else {
                rS += s
            }
        }
    }
} else {
    for (let i = 0; i < s2.length; i++) {
        let s = s2[i]
        if (i < s1.length) {
            x = Number(s) + Number(s1[i]) + carry
            rS += String((x % 10))
            carry = parseInt(x/10)
        } else {
            if (carry) {
                x = Number(s) + carry
                rS += String((x % 10))
                carry = parseInt(x/10)
            } else {
                rS += s
            }
        }
    }
}
if (carry) {
    rS += String(carry)
}
return rS.split("").reverse().join("")
}

Example: addTwoStr('120354566', '321442535') Output: "441797101"



来源:https://stackoverflow.com/questions/4557509/javascript-summing-large-integers

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!