break_eternity.js icon indicating copy to clipboard operation
break_eternity.js copied to clipboard

Can't convert BigInt to Decimal without setting its value to 0

Open James103 opened this issue 2 years ago • 8 comments

Currently (latest break_eternity.js version as of 2023-01-07), attempting to convert a BigInt value to Decimal will return 0. Furthermore, a string that represents a number (generated by BigInt.toString()) will also return 0 if the number the string represents is at least 21024.

Console output with test cases:

new Decimal(String(2n**1022n)).toString() // 1
'4.494232837155819e307'

new Decimal(String(2n**1032n)).toString() // 2
'0'

new Decimal(1234n).toString() // 3
'0'

new Decimal(2n**1234n).toString() // 4
'0'
  1. Correct
  2. Incorrect; should be 21032 or about 4.602094e310
  3. Incorrect; should be 1234
  4. Incorrect; should be 21234 or about 2.958112e371

Discovered whilst writing migration code for an incremental game to convert various save data from BigInt values to their proper Decimals.

James103 avatar Jan 07 '23 23:01 James103

Woah, I haven't seen this '2n' thing before. Is it a new Javascript feature?

Patashu avatar Jan 08 '23 00:01 Patashu

Woah, I haven't seen this '2n' thing before. Is it a new Javascript feature?

The syntax used describes something called BigInts, which are supported on the most recent version of all major browsers. BigInts effectively allow storing numbers much larger than 21024 with full precision (down to the nearest whole number), with their size effectively only being limited only by available memory.

For more information on BigInts, see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt

James103 avatar Jan 08 '23 00:01 James103

Cutting edge! I'll take a look at supporting BigInts if I find the time and mood.

Patashu avatar Jan 08 '23 07:01 Patashu

You can convert a BigInt to a String with String(bigint) or bigint.toString() and you can construct a Decimal from a string of digits with new Decimal(string). However, Decimal.fromString fails to properly parse strings of digits that are more than 309 digits long, as such strings become Infinity when coerced to Number.

Number("1".repeat(309))
1.1111111111111112e+308

Number("1".repeat(310))
Infinity

James103 avatar Jan 08 '23 14:01 James103

I guess it'd be sufficient to detect the string is longer than 300 digits, grab the first 18 of them, and turn it into mantissa and exponent.

Patashu avatar Jan 08 '23 23:01 Patashu

#145 will fix it

1231234md5 avatar Jan 14 '23 02:01 1231234md5

I guess it'd be sufficient to detect the string is longer than 300 digits, grab the first 18 of them, and turn it into mantissa and exponent.

Couldn't you toString() the bigint, remove the n from the string then let toString() method do it's job as usual?

jakub791 avatar Feb 03 '23 22:02 jakub791

I guess it'd be sufficient to detect the string is longer than 300 digits, grab the first 18 of them, and turn it into mantissa and exponent.

Couldn't you toString() the bigint, remove the n from the string then let toString() method do it's job as usual?

but that's what #145 does.

1231234md5 avatar Feb 04 '23 09:02 1231234md5