0

I'm trying to write a function that calculates and displays cryptocurrency values with subtracted fees (-0.10000000 in the example for simplicity).

But I can't get it to display correct values for large numbers (and as this is about currency, correct values are somewhat important)...

Please see this fiddle https://jsfiddle.net/vbr3q0u1/19/ to see the problem.

my first idea was

$('#result').text(amount ? (amount + fees).toFixed(8) > 0 ? (amount + fees).toFixed(8) : 0 : 0)

but that yields the following results:

10000000.55555555 // 10000000.45555555  (correct)
100000000.55555555 // 100000000.45555556 (off by .00000001)
1000000000.55555555 // this time the INPUT div shows 1000000000.55555558
10000000000.55555555 // input shows 10000000000.55555534, result shows 10000000000.45555496

so there's obviously something wrong there... so then i thought "ok, i know javascript is strange with floats and i've always heard it's better to convert to int, calculate, then convert back to float".

so i tried

$('#result').text(amount ? (amount + fees).toFixed(8) > 0 ? (((amount + fees) * 100000000) / 100000000) : 0 : 0)

with following results:

10000000.55555555 // 10000000.45555555 (correct)
100000000.55555555 // 100000000.45555556 (same as above, so there's a pattern here)
1000000000.55555555 // 1000000000.55555558 / 1000000000.4555556 (yup, same values as above)
10000000000.55555555 // 10000000000.55555534 / 10000000000.455555 (now it's getting weird)
...
100000000000000.55555555 // shows 100000000000000.56250000 as input and 100000000000000.47 as result...

So I am obviously doing something wrong.. How can i make the function calculate the result CORRECTLY (with 8 decimals) and what am I doing wrong in my two attempts?

thank you very much :)

edit

yeah.. i know (as i wrote in my question) that float math is broken. but my question is how i can correctly convert/etc the numbers to get the correct result, and what is wrong about the way i tried to do it

devman
  • 641
  • 1
  • 8
  • 26
  • If this is about currency, don't use JavaScript's built-in numbers (or use only whole numbers in the range `-Number.MAX_SAFE_INTEGER` through `Number.MAX_SAFE_INTEGER`, for instance by multiplying by 100 if to-the-penny accuracy is all you need [or by 1000 if to the-tenth-of-a-penny, or...]). Look into "big number" or "bit integer" libraries instead. (There's a [`BigInt` proposal](https://github.com/tc39/proposal-bigint) for JavaScript at Stage 3, if multiplying would take you out of the safe range of number.) – T.J. Crowder Jun 11 '18 at 17:20
  • @T.J.Crowder so.... multiply by 10000000 right when reading from the input for 8-digit precision? i'm afraid that will overflow sooner or later. is that BigInt proposal .."usable"? or is it just an idea we'll have to wait for? – devman Jun 11 '18 at 17:24
  • 1
    Yes, that would be right for eight-decimal precision, which would mean the largest positive number you could reliably handle would be 90071992.5474099 (just over 90 million). `BigInt` isn't usable in the wild yet (though it's getting close). If you search for "big number" you'll find at least a couple of libs. Good luck! – T.J. Crowder Jun 11 '18 at 18:38

0 Answers0