proposal-decimal
proposal-decimal copied to clipboard
How should the BigDecimal constructor round Numbers?
A couple options, suggested by Fabrice Bellard:
(1) BigDecimal(0.1) = 0.1d (i.e. use Number.prototype.toString() and then convert the string to bigdecimal).
(2) BigDecimal(0.1) = 0.1000000000000000055511151231257827021181583404541015625d
(2) is mathematically correct but may be surprising, so I selected (1).
I have to say, I was really expecting (2), but (1) may be more practical. One way to think of a Number is an exact quantity, and another way is to think of it as a range within the ulp.
I'd definitely expect (1); i'd be surprised if most people found the actual Number being represented to be an intuitive result.
Hi!
(2) looks better to me.
and there is two questions, actually:
- The default scale for Numbers.
- The default rounding mode.
Take a look: https://repl.it/repls/ApprehensiveRobustAssignment
It can take a string like in Java
(1) BigDecimal(‘0.1’) = 0.1d
Second variant is finite for Decimal128, but for BigDecimal it’s infinite expression, how it should be stored? Seems that second variant impossible.
0.1000000000000000055511151231257827021181583404541015625…
Also here example with BigInt:
let x = BigDecimal(14677443357n.toString());
@munrocket
the second variant is finite,
0.1).toFixed(100) === 0.1000000000000000055511151231257827021181583404541015625000000000000000000000000000000000000000000000
(as the number can be represented as
Another options is to allow BigDecimal.round to accept numbers and strings:
BigDecimal.round(0.1, {maximumSignificantDigits: 15, roundingMode: 'half-up'}); // 0.1d BigDecimal.round(0.1, {maximumSignificantDigits: 1074, roundingMode: 'half-up'}) // 0.1000000000000000055511151231257827021181583404541015625d
Yea :) I am tried to find this issue when I understand that was wrong, but lost in this repo. So, I just waited when someone fixing this comment :D
Just chiming in to this old issue:
The current approach is (1).
For users who know what they're doing, you can achieve (2) by converting a Number to a String e.g. with toFixed, producing a String that with a large number of significant digits, then constructing a decimal from that string. (But NB if you that input string has more than 34 significant digits, the resulting decimal will be obtained by first rounding the input value.)