At this point it’s common wisdom among software developers that if you’re going to store amounts of currency, you shouldn’t use floating-point numbers. Floats can represent numbers within a huge range, but only some numbers in that range can be represented exactly, and while this is fine sometimes it’s almost never what you want when dealing with money.

I got to wondering: counting up cent by cent from zero, where would you first run into a problem if you were using a float to store an amount in dollars? (For U.S. currency, the base unit is the dollar and the smallest subdivision is the cent, which is one hundredth of a dollar.)

If we want to express a number exactly in binary floating point, one requirement is that we be able to write it as a fraction p/q in lowest terms, where p and q are integers and q = 2n for some integer n.1 Let’s consider the smallest nonzero amount of currency: one cent. Expressed in dollars, this amount is 0.01, or 1/100. The denominator, 100, cannot be written as 2n for any integer n, so 0.01 cannot be expressed exactly as a binary floating-point number. Notice that we didn’t even get as far as asking whether it would be representable in an IEEE float, or double, or any other specific format—the decimal number 0.01 just can’t be represented by any finite string of binary digits, period.

So there we have our answer: the problems with representing decimal amounts in floats start with the “first” decimal amount, at least as far as dollars and cents go. Of course, if you were to write double x = 0.01 in your program and then do some calculations with x, your results wouldn’t necessarily be wrong—but they wouldn’t necessarily be right, either.

  1. According to a Stack Overflow answer by Alexander Yee, “A number can be represented exactly in binary if the prime factorization of the denominator contains only 2.” This might seem to suggest that integers aren’t exactly representable, but they are. A more precise statement would be, “…if the denominator is unity or if its prime factorization contains only powers of 2.”↩︎