Live data from Hacker News

How to Handle Monetary Values in JavaScript

frontstuff.io

11–20 of 115 posts

Re: How to Handle Monetary Values in JavaScript

#12
post #3

I looked into using Dinero.js before but it was overkill for my use case of calculating cart totals in USD only. I went with Big.js because it was better suited for what I wanted: a small library for decimal arithmetic.

Can you illustrate a case where you can't use regular FP arithmetic and round to 2 decimal places at the end?

Bring up a Javascript interpreter and try this:

    $ node
    > 0.1 + 0.2 - 0.3
    5.551115123125783e-17
Close enough for trivial cases but errors can accumulate.

Ruby, Perl5, Python also fail this. Perl6 uses Rat numbers for things like this and doesn't have this problem.

Re: How to Handle Monetary Values in JavaScript

#14
post #3

I looked into using Dinero.js before but it was overkill for my use case of calculating cart totals in USD only. I went with Big.js because it was better suited for what I wanted: a small library for decimal arithmetic.

Can you illustrate a case where you can't use regular FP arithmetic and round to 2 decimal places at the end?

Sure. Divide by two with any kind of predictability.

for (let n = 0; n < 1; n += .01) { console.log(`n: ${n}, half: ${(n / 2).toFixed(2)}`); }

Re: How to Handle Monetary Values in JavaScript

#15

I looked into using Dinero.js before but it was overkill for my use case of calculating cart totals in USD only. I went with Big.js because it was better suited for what I wanted: a small library for decimal arithmetic.

I think the advantage behind using something like Big.js is to future proof the code against hyper-inflation. Though a dedicated currency engine would better have the ability to set and conveniently update the currency denomination of stored values to cope with this.

With float64's maximum 'safe' integer at almost ten thousand trillion, I believe this should be enough to compute most commercial transactions securely as long as the amounts base denomination is up to date (eg cents or dollars or megadollars).

The quantization noise mentioned in this article is possible to round off when appropriate.

  function round_tail_digits(c){ 
    return Math.round(c*1e15)/1e15
  }

  function round_at_hundreds(c){
    return Math.round(c*100)/100
  }

Re: How to Handle Monetary Values in JavaScript

#16
post #9
post #3

Earlier quoted context omitted.

Can you illustrate a case where you can't use regular FP arithmetic and round to 2 decimal places at the end?

(1.005).toFixed(2) // Expected rounding to "1.01" "1.00"

cases like that's everywhere.

2.875.toFixed(2) = "2.88" while 2.675.toFixed(2) = "2.67"

7205759403792794 + 1.1 = 7205759403792795

7205759403792794 + 1.9 = 7205759403792796

Re: How to Handle Monetary Values in JavaScript

#17
post #5

Earlier quoted context omitted.

You can't model 1.0 correctly but it will be something like 1.000006667. If you add enough of these numbers you will be off.

Your details are off. 1.0 is precisely representable in double precision floating point with no error.

Sorry, picked the wrong number. But I think the general idea is correct.

Re: How to Handle Monetary Values in JavaScript

#18
Banking apps, e-commerce websites, stock exchange platforms, we interact with money daily. We also increasingly rely on technology to handle ours.

Yet, there’s no consensus around how to programmatically handle monetary values.

I wonder if the average person would find this frightening.

Re: How to Handle Monetary Values in JavaScript

#19
post #4

I really like the approach Perl 6 takes with FatRat[1]. You basically have an object which holds a numerator and denominator, so all arithmetic calculations do not loose precision. [1] https://docs.perl6.org/type/FatRat

Clojure does this out of the box: `(/ 1 3)` is 1/3. Removes a lot of annoying floating point errors.

Re: How to Handle Monetary Values in JavaScript

#20
post #12
post #3

Earlier quoted context omitted.

Can you illustrate a case where you can't use regular FP arithmetic and round to 2 decimal places at the end?

Bring up a Javascript interpreter and try this: $ node > 0.1 + 0.2 - 0.3 5.551115123125783e-17 Close enough for trivial cases but errors can accumulate. Ruby, Perl5, Python also fail this. Perl6 uses Rat numbers for things like this and doesn't have this problem.

You'd need to accumulate 10^14 such errors to be off by an entire penny, which doesn't seem relevant to a web shopping cart.
Post reply on HN