Count number of digits after `.` in floating point numbers?
I doubt this is what you want since the question is asking for something that's not usually meaningful with floating point numbers, but here is the answer:
int digits_after_decimal_point(double x)
{
int i;
for (i=0; x!=rint(x); x+=x, i++);
return i;
}
The problem isn't really solvable as stated, since floating-point is typically represented in binary, not in decimal. As you say, many (in fact most) decimal numbers are not exactly representable in floating-point.
On the other hand, all numbers that are exactly representable in binary floating-point are decimals with a finite number of digits -- but that's not particularly useful if you want a result of 2 for 3.44
.
When I run your code snippet, it says that 3.44
has 2 digits after the decimal point -- because 3.44 * 10.0 * 10.0
just happens to yield exactly 344.0
. That might not happen for another number like, say, 3.43
(I haven't tried it).
When I try it with 1.0/3.0
, it goes into an infinite loop. Adding some printf
s shows that no
becomes exactly 33333333333333324.0
after 17 iterations -- but that number is too big to be represented as an int
(at least on my system), and converting it to int
has undefined behavior.
And for large numbers, repeatedly multiplying by 10 will inevitably give you a floating-point overflow. There are ways to avoid that, but they don't solve the other problems.
If you store the value 3.44
in a double
object, the actual value stored (at least on my system) is exactly 3.439999999999999946709294817992486059665679931640625
, which has 51 decimal digits in its fractional part. Suppose you really want to compute the number of decimal digits after the point in 3.439999999999999946709294817992486059665679931640625
. Since 3.44
and 3.439999999999999946709294817992486059665679931640625
are effectively the same number, there's no way for any C function to distinguish between them and know whether it should return 2 or 51 (or 50 if you meant 3.43999999999999994670929481799248605966567993164062
, or ...).
You could probably detect that the stored value is "close enough" to 3.44
, but that makes it a much more complex problem -- and it loses the ability to determine the number of decimal digits in the fractional part of 3.439999999999999946709294817992486059665679931640625
.
The question is meaningful only if the number you're given is stored in some format that can actually represent decimal fractions (such as a string), or if you add some complex requirement for determining which decimal fraction a given binary approximation is meant to represent.
There's probably a reasonable way to do the latter by looking for the unique decimal fraction whose nearest approximation in the given floating-point type is the given binary floating-point number.
The question could be interpreted as such:
Given a floating point number, find the shortest decimal representation that would be re-interpreted as the same floating point value with correct rounding.
Once formulated like this, the answer is Yes we can - see this algorithm:
Printing floating point numbers quickly and accurately. Robert G. Burger and R. Kent Dybvig. ACM SIGPLAN 1996 Conference on Programming Language Design and Implementation, June 1996
http://www.cs.indiana.edu/~dyb/pubs/FP-Printing-PLDI96.pdf
See also references from Compute the double value nearest preferred decimal result for a Smalltalk implementation.