6

I am trying to convert a string to a big integer to perform some arithmetic calculations. However, when I try this:

Number("9007199254740993")

...I am getting this unexpected result:

9007199254740992

I suspect that this is probably because of the limit on the size of integers that Number is capable of working with.

Basically, I want to check if two strings are consecutive numbers or not. Since Number is not returning the correct value, I am getting the incorrect difference for "9007199254740993" and "9007199254740992". Specifically, I am expecting 1, but getting 0.

One possibility I considered is dividing each number by a factor to make each of them smaller. Is there any other solution?

4
  • 3
    BigInt (stage 3 proposal), a "big number" library, or none at all because your requirement can be fulfilled without converting them into real numbers. Commented Dec 29, 2018 at 17:50
  • See stackoverflow.com/questions/45694479/… Commented Dec 29, 2018 at 17:57
  • @ChrisHappy. Thanks for the link. I searched if there was already a similar question, but could not find then. Commented Dec 29, 2018 at 18:13
  • @VikramKumar I have updated my code. Commented Dec 29, 2018 at 19:09

4 Answers 4

3

Javascript's Number type is a numeric data type in the double-precision 64-bit floating point format (IEEE 754).

If you are dealing with large integers, use a BigInt or a corresponding library.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the tip on BigInt. Hopefully it will be supported by all browsers soon.
1

I you don't want to rely on BigInt and only have positive integers in mind, you can also write the successor test yourself. Full code in the snippet below.


Notes

A string representation of a positive integer is easily convertible to a decimal array where the index represents the exponent to the base 10. For example "42" ~> [2, 4] (since 42 = 2*10^0 + 4*10^1). You can also just as easily convert it back.

Now for the successor test you just need to define the increment operation (which is just adding 1 with carry). With that you can just compare if the increment of one number is equal to the unincremented other number (and vice versa).


Code

// Convert a string representation of positive decimal integer to an array of decimals.
const toArray = numberString => Array.from(numberString, c => parseInt(c))
    .reverse();

// Convert the array representation of a positive decimal integer string back to the corresponding string representation (this is the inverse of `toArray`).
const fromArray = numberArray => numberArray.map(String)
    .reverse()
    .join('');

console.log(fromArray(toArray("9007199254740993")) === "9007199254740993"); // true

// Perform the increment operation on the array representation of the positive decimal integer.
const increment = numberArray => {
  let carry = 1;
  const incrementedNumberArray = [];
  numberArray.forEach(i => {
      let j;
      if (carry === 0) {
          j = i;
      } else if (carry === 1) {
          if (i === 9) {
              j = 0;
          } else {
              j = i + 1;
              carry = 0;
          }
      }
      incrementedNumberArray.push(j);
  });

  if (carry === 1) { 
    incrementedNumberArray.push(1);
  }

  return incrementedNumberArray;
};

console.log(fromArray(increment(toArray("9007199254740993"))) === "9007199254740994"); // true
console.log(fromArray(increment(toArray("9999999999999999"))) === "10000000000000000"); // true

// Test if two strings represent positive integers where one is the other's successor.  
const isSuccessor = (a, b) => {
  const a_ = increment(toArray(a));
  const b_ = increment(toArray(b));
  return fromArray(a_) === b || fromArray(b_) === a;
};

console.log(isSuccessor("9007199254740993", "9007199254740994")); // true
console.log(isSuccessor("9007199254740994", "9007199254740993")); // true
console.log(isSuccessor("9999999999999999", "10000000000000000")); // true
console.log(isSuccessor("10000000000000000", "9999999999999999")); // true
console.log(isSuccessor("10000000000000000", "10000000000000002")); // false

Comments

1

You can use BIG integer library like one in JAVA. check here

npm install big-integer

var bigInt = require("big-integer");
var largeNumber1 = bigInt("9007199254740993");
var largeNumber2 = bigInt("9007199254740994"); // any other number
var ans = largeNumber1.minus(largeNumber2);
if(ans == 1 || ans == -1){
console.log('consecutive ')
}else{
console.log('not consecutive ')
}

1 Comment

Thanks for the library big-integer. Unfortunately I am looking for a native solution (Cannot include third-party library). I'll implement Neeraj solution for now.
1

Note: I recommend you to use BigInt(as suggested by @Andreas in comment), if you are dealing with Big Numbers.


UPDATED

Use this code to compare big positive integers(The arguments should be in string format)

function compareBigNumber(num1, num2) {
  if (num1 > Number.MAX_SAFE_INTEGER && num2 > Number.MAX_SAFE_INTEGER) {
    var newNum1 = num1.split('').reverse();
    var newNum2 = num2.split('').reverse();
  
    do {
      newNum1.pop();
      newNum2.pop();
    } while (newNum1[newNum1.length-1] === '0' || newNum2[newNum2.length-1] === '0')
    
    return compareBigNumber(newNum1.reverse().join(''), newNum2.reverse().join(''));
  } else if(num1 > Number.MAX_SAFE_INTEGER){ 
    return 'num1 is greater' 
  } else if (num2 > Number.MAX_SAFE_INTEGER) {
    return 'num2 is greater'
  }
  else {
    var num1Int = parseInt(num1);
    var num2Int = parseInt(num2);
    if (num1Int > num2Int) {
      return 'Num1 is greater';
    } else if (num2Int > num1Int){
      return 'Num2 is greater'
    } else {
      return 'Num1 is equal to Num2';
    }
  }
}

console.log(compareBigNumber("9007199254740992", "9007199254740993"))
console.log(compareBigNumber("100000000000000000000", "0"))

2 Comments

@Vikram Kumar . The answer here is wrong (may be work in your case but can not generalize) as if you took number 90071992547409921 and 90071992547409922 then ans will be same (as both number after /10 give same number)
compareBigNumber("1000000000000000000000", "0") returns "Num1 is equal to Num2". Seems like you make some assumptions about the code which do not hold in this case.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.