79704712

Date: 2025-07-17 11:26:47
Score: 3.5
Natty:
Report link

How do I get the decimal places of a floating point number?

It seems so simple, right? A fractional number like 123.456 consists of three integer digits 123, and a decimal point ., and then three more fractional digits 456. How hard can it be to extract the fractional digits 456, or even simpler, just find out how many of them there are?

And as the answers here show, the answer to "How hard can it be?" is "Pretty hard". There are lots of techniques presented here, but they're all complicated, and some of them involve unnecessary-seeming conversions back to strings. Some of these techniques are error-prone, or don't work properly on all inputs.

And it turns out that the reason the problem is hard is that the premise is flawed. Internally to a computer, the decimal fraction 123.456 is not represented as three integer digits 123, and a decimal point ., and then three fractional digits 456. Nothing like that.

As you probably know, computers use binary, or base 2, for just about everything. They don't use decimal (base 10). So how do computers represent fractions, if not in the obvious way?

Let's look first at a slightly different decimal fraction, 123.625. That's equal to 123⅝, which is going to make it easier to see in base two. 123.625 is represented internally as the binary fraction 1.111011101, times a scaling factor of 26, or 64. Let's check that: 1.111011101 is 1.931640625, and 1.931640625 × 64 = 123.625. Check.

But what about 123.456? Since the fractional part .456 is not representable as a binary fraction made up of halves and quarters and eighths and sixteenths, it's not going to work so well.

In the IEEE 754 double-precision floating point format used by most JavaScript implementations, the number 123.456 is represented by the binary number 1.1110110111010010111100011010100111111011111001110111, again multiplied by 26. But if you do the math, this works out to about 123.45600000000000307. It is not exactly equal to 123.456.

This is a big surprise the first time you encounter it. Binary floating-point representations such as are used by JavaScript (and in fact most computers and programming languages) can not represent decimal fractions like 123.456 exactly.

And since the internal, binary representation of 123.456 does not involve the digits 123 or 456, it is not so easy to extract them in that form, after all.

And, not only is it not so easy to directly extract the fractional digits 456, it's problematic to even ask how many of them there are. As I said, once you've read in a number like 123.456 into a JavaScript program, it's represented internally by the binary fraction 1.1110110111010010111100011010100111111011111001110111 × 26, which works out to about 123.45600000000000307. So should we say that this number has 17 digits past the decimal? No, and it's even worse than that: I said that the internal binary representation works out to the equivalent of "about 123.45600000000000307", but it works out to exactly 123.4560000000000030695446184836328029632568359375, which has 46 digits past the decimal.

The answers presented here use various tricks, such as rounding or string conversion, to get around this problem. The answers presented here tend to give the answer 3 for the alleged number of places past the decimal for the input number 123.456. But since that input number 123.456 isn't really 123.456, these answers are, to some extent, cheating. And, indeed, if you take a function that can "correctly" give the answer 3 for the precision of the input 123.456, it will also give the answer 3 for input values of 123.45600000000000307 or 123.4560000000000030695446184836328029632568359375. (Try it!)

So how do you get around this problem? How do you find the true precision of the input number 123.456, if by the time you're working with it it's really a number like 123.45600000000000307? There are ways, but before choosing one, you have to ask: why do you need the precision, actually?

If it's an academic exercise, with little or no practical value, the techniques presented in the answers here may be acceptable, as long as you understand the underlying meaninglessness of the exercise.

But if you're trying to perform operations on the user's input in some way, operations which should reflect the user's actual input precision, you may want to initially take the user's input as a string, and count the number of places past the decimal in that representation, before converting the input string to a number and performing the rest of your operations. In that way, not only will you trivially get the right answer for an input of "123.456", but you will also be able to correctly determine that user input of, say, "123.456000" should be interpreted as having six places past the decimal.

Reasons:
  • Blacklisted phrase (1): How do I
  • Blacklisted phrase (1): how do you
  • Blacklisted phrase (1): How do you
  • RegEx Blacklisted phrase (2.5): do you find the
  • Long answer (-1):
  • Has code block (-0.5):
  • Contains question mark (0.5):
  • Starts with a question (0.5): How do I
  • Filler text (0.5): 00000000000
  • Filler text (0): 00000000000
  • Filler text (0): 00000000000
  • Filler text (0): 00000000000
  • Filler text (0): 00000000000
  • Filler text (0): 00000000000
  • Filler text (0): 00000000000
  • High reputation (-2):
Posted by: Steve Summit