question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Why not use float?

See original GitHub issue

This is a legitimate question. I’m doing research on financial math, and I don’t really understand why you’re using integers, when you can use floating point numbers.

Yes, floating point numbers are not guaranteed to be exact, but integers also have limitations. Since you tend to default to a precision of 2 digits, I can’t think of a (reasonable size) calculation where you can just use a floating point number and round with toFixed() for display.

I hope this is not taken as a criticism, I’m just trying to learn. I wrote some notes on my blog but I would love to understand if I’m incorrect.

Issue Analytics

  • State:closed
  • Created 5 years ago
  • Comments:12 (3 by maintainers)

github_iconTop GitHub Comments

2reactions
scurkercommented, Dec 6, 2018

This is a great question! I’ll try to summarize as best I can.

Integers (or some other representation such as Decimals, or BigNumber) always have 100% precision. There is no precision loss outside of the limitations of Number.MAX_SAFE_INTEGER if you’re using integers; other methods may have other restrictions. If currencies always had an exact precision of 2, you would be correct that toFixed(2) likely would work in those cases.

Unfortunately, currencies don’t always end up with a precise number and that’s where things can start to cause trouble. Taxes and other percentage calculations happen with a result that ends up with a number less than .01, so we have to decide how to round. Since a floating point number can end up higher or lower than the real value, using toFixed(2) can actually round in the wrong direction, leading to missing or added cents.

Let me explain with an example:

(17.955).toFixed(2); // => "17.95"
(17.954 + .001).toFixed(2); // => "17.96"

Both numbers should be exactly the same (17.955), but they actually aren’t in reality since floating point precision can’t accurately store every decimal number. Sometimes the same number can be rounded up, or rounded down depending on how that number was eventually reached. If the number beyond the precision is .004999999~ or less, it’ll round down to .00. If it’s larger than that it’ll round up. It doesn’t really matter where that number is, so even a number as small as .00000000000000001 can cause the final precision to be off by a cent if it’s on the wrong side of the half cent.

And while the default precision is 2, the precision doesn’t really matter since we deal in integers. We can safely deal in whatever precision you would like (again up to Number.MAX_SAFE_INTEGER).

1reaction
tmorehousecommented, Dec 6, 2018

Some fixed point numbers (specifically the fractional portion) cannot be stored in binary floats without issues.

Take for example:

a = 0.1 // => 0.1
b = 0.2 // => 0.2
a + b   // => 0.30000000000000004

Over numerous computations this error can grow larger and larger when doing currency math.

A good article on Javascript and currecy is https://frontstuff.io/how-to-handle-monetary-values-in-javascript

Using a decimal system has advantages, but raises a major issue when it comes to programming. Computers use a binary system, so they can’t natively represent decimal numbers. Some languages have come up with their own solutions like the BigDecimal type in Java or the decimal type in C#. JavaScript only has the Number type, which can be used as an integer or a double precision float. Because it’s a binary representation of a base 10 system, you end up with inaccurate results when you try to do math. Using floats to store monetary values is a bad idea. As you calculate more values, the imperceptible precision errors lead to larger gaps. This inevitably ends up causing rounding issues.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Why You Should Never Use Float and Double for Monetary ...
Float and double are bad for financial (even for military use) world, never use them for monetary calculations. If precision is one of...
Read more >
Why not use Double or Float to represent currency?
The float and double types are particularly ill-suited for monetary calculations because it is impossible to represent 0.1 (or any other negative power...
Read more >
Floating Point Numbers & Currency Rounding Errors
Because floats and doubles cannot accurately represent the base 10 multiples we use for money, so it is impossible to represent 0.1 (or...
Read more >
Never Use Floats for Money
Why floats are bad for money. We would think yeah, floats would be great for money, because $1.40 is 1 dollar and 4...
Read more >
For values in C# and C, why don't you just always use floats?
When choosing a data type, it's best to choose a type that adequately represents the anticipated data. Using a float to represent a...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found