Open littledan opened 4 years ago
It would be really confusing if mixed Number and BigDecimal expression will not throw. This can lead to hard to debug errors. Mixed BigInt and BigDecimal expressions make more sense, though it probably will be safer to cast to BigDecimal explicitly.
What makes the errors hard to debug?
Sorry, "mistake" is a better word. I mean that if developer will mix Number and BigDecimal by mistake, it will be hard to find out if and why the number of decimal places was changed. In financial web apps it's a very common group of bugs (MPI, pips and a lot of other things may have different number of decimal places and that number is very important and shouldn't be changed accidentally)
Note, if you have a bunch of BigDecimal values with different numbers of decimal places, it would be fine to mix them in calculations--they are all the same type.
I guess @chicoxyzzy mean mixed Number
(binary 64-bits floats) with BigDecimal
(decimal floats with arbitrary precision). This definitely shouldn't be possible implicitly.
Would it solve this problem if you could use the BigDecimal constructor to explicitly cast the Number to a BigDecimal before performing the operation?
If it’ll be possible to set a number of decimal places via constructor parameter or at least round by some BigDecimal instance method after the cast, then yes
Exactly. The same way as we do this for mixing BigInt
with Number
nowadays.
I imagine the constructor will give the exact value (to keep things simple), and then you could use a round method on the result. If you could document requirements for a round method in #14 (or should we break it out into a separate issue?), that would be great
I'm not sure I'm happy with the combination of *
always returning exact results and BigDecimal having arbitrary precision. It's too easy for the precision to run away from you if you're not careful, and I suspect most users won't be careful. You can do simple things like squaring 1.0000001m
30 times and running out of memory despite the result being fairly small. This is not an issue with IEEE decimal because it does round.
@waldemarhorwat Do you think we should limit to IEEE decimal size, as suggested in #8 ? Maybe that would be a helpful place to follow up.
It's a fairly broad question. I think that IEEE decimal (without distinguishing cohorts) has more predictable behavior and applicability — you can do math, trigonometric functions, etc., and they behave just as in IEEE double without worries about falling off a cliff because precision is exploding somewhere inside your algorithm. Unlimited precision decimal is much harder to use safely. Similarly, I'd much rather get an infinity than an exception if I try to compute the tangent of 90°.
@waldemarhorwat Perhaps one way to allay the concern about trigonometric functions and other elementary functions would be to indicate that those operations need to have a precision attached to them? In other words, only the "easy" stuff like addition, subtraction, multiplication, and division (and, possibly, a couple more operations) work in an unlimited way (though one may optionally specify a precision there, too), but logarithms, sine, cosine, etc., require a precision.
This proposal follows BigInt in TypeErrors on mixed operands, e.g., BigInt + BigDecimal -> TypeError. Although it is possible to losslessly convert any Number or BigInt to a BigDecimal, the strictness here is intended to be part of a consistent mental model that developers should keep track of their numerical types and ensure uniformity. (The exception is comparison operators, which allow mixed types.) If people have concerns about this model, let's talk them through in this thread.