How to check if a double has at most n decimal places?

The test fails, because you have reached the accuracy of the binary floating point representation, which is approximately 16 digits with IEEE754 double precision. Multiplying by 649632196443.4279 by 10000 will truncate the binary representation, leading to errors when rounding and dividing afterwards, thereby invalidating the result of your function completely.

For more details see http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems

A better way would be to check whether the n+1 decimal places are below a certain threshold. If d - round(d) is less than epsilon (see limit), the decimal representation of d has no significant decimal places. Similarly if (d - round(d)) * 10^n is less than epsilon, d can have at most n significant places.

Use Jon Skeet's DoubleConverter to check for the cases where d isn't accurate enough to hold the decimal places you are looking for.


If your goal is to represent a number with exactly n significant figures to the right of the decimal, BigDecimal is the class to use.

Immutable, arbitrary-precision signed decimal numbers. A BigDecimal consists of an arbitrary precision integer unscaled value and a 32-bit integer scale. If zero or positive, the scale is the number of digits to the right of the decimal point. If negative, the unscaled value of the number is multiplied by ten to the power of the negation of the scale. The value of the number represented by the BigDecimal is therefore (unscaledValue × 10-scale).

scale can be set via setScale(int)


As with all floating point arithmetic, you should not check for equality, but rather that the error (epsilon) is sufficiently small.

If you replace:

return (d==check);

with something like

return (Math.abs(d-check) <= 0.0000001);

it should work. Obviously, the epsilon should be selected to be small enough compared with the number of decimals you're checking for.


The double type is a binary floating point number. There are always apparent inaccuracies in dealing with them as if they were decimal floating point numbers. I don't know that you'll ever be able to write your function so that it works the way you want.

You will likely have to go back to the original source of the number (a string input perhaps) and keep the decimal representation if it is important to you.