Reputation: 979
When we don't know the numerical value at advance, can we convert it to BigInt or String without value corruption?
const targetNumber: number = 90071992547409946; // suppose we don't know it in advance
function splitEach3DigitsGroupWithComma(targetNumber: number | bigint | string): string {
if(targetNumber > Number.MAX_SAFE_INTEGER) {
// targetNumber = BigInt(targetNumber); // 90071992547409952n
// targetNumber = String(targetNumber); // 90071992547409950
// We need to do something before proceed!
}
return String(targetNumber).replace(/\B(?=(?:\d{3})+(?!\d))/gu, ",");
}
Upvotes: 0
Views: 1599
Reputation: 26191
If your number is bigger than Number._MAX_SAFE_INTEGER
then you can not safely convert into BigInt
as is.
Say your big integer is 134640597783270600
which is > Number._MAX_SAFE_INTEGER
. If you do like
> n = 134640597783270600;
> BigInt(n);
<- 134640597783270592n // Wrong..!
So you should first check if n
is bigger than Number._MAX_SAFE_INTEGER
and if so just convert it to string first
> BigInt(n > Number.MAX_SAFE_INTEGER ? n+"" : n);
<- 134640597783270600n // Correct..!
However, if n
happens to be a big integer expressed in the exponential form like 7.576507751994453e+29
then this happens;
> BigInt(7.576507751994453e+29+"");
Uncaught SyntaxError: Cannot convert 7.576507751994453e+29 to a BigInt
at BigInt (<anonymous>)
at <anonymous>:1:1
At this time i think to be on the safe side, it's best to convert all those integers greater than Number.MAX_SAFE_INTEGER
into String
type first to test for exponential representation. So, despite we have a BigInt
constructor in JS, apparently we still need a function.
function toBigInt(n){
return n.toString().includes("e") ? BigInt(n)
: BigInt(n+"");
}
Upvotes: 1
Reputation: 370989
If the targetNumber
is neither already a BigInt nor a string at the point where you first can work with it, then it's a plain number - and in that case, it may only be as precise as a number can be, per the IEEE 754 standard. If you only have a number
to work with to begin with, possible more precise values have already been lost earlier.
To maintain precision, ensure that the value stays as a BigInt or string from beginning to end. If it gets converted to a number
at any time in between, and then that number gets used, it may have lost precision, depending on the number.
In other words, to do something like this, you need to start with something like
const targetNumber = '90071992547409946';
or
const targetNumber = 90071992547409946n;
It can't be done in the middle of the process, once you already only have a number
, while maintaining precision.
Upvotes: 1