MikeMcl / decimal.js

An arbitrary-precision Decimal type for JavaScript
http://mikemcl.github.io/decimal.js
MIT License
6.45k stars 475 forks source link

Using comparison operators with Decimals can give the wrong result #172

Open kynan opened 3 years ago

kynan commented 3 years ago

The following behavior is somewhat confusing:

const { Decimal } = require('decimal.js');
five = new Decimal(5);
ten = new Decimal(10);
five < ten   // false
five <= ten  // false
ten > five   // false
ten >= five  // false

I'm aware there's dedicated comparison operators, but why does "elementary" comparison give the wrong result in this case?

MikeMcl commented 3 years ago

The relational operators cause valueOf to be called on each Decimal, which returns string values which are then compared 'alphabetically', and '5' comes after '1'.

kynan commented 3 years ago

That does indeed make a lot of sense, thanks for the explanation! The joys of lexicographic comparison. And of course you can't have valueOf return a numeric value as that may lose precision.

Worth mentioning this in the docs as a caveat?

MikeMcl commented 3 years ago

As I did recently with big.js, in the next major release I may throw on calls to valueOf to prevent accidental usage of Decimals with arithmetic and relational operators.

kynan commented 3 years ago

That's even better, as people don't read documentation :)