I'm trying to count the number of digits in fractional part of double, but something is going wrong and I getting infinite loop:
double pi = 3.141592;
int counter = 0;
for (; pi != int(pi); ++counter)
pi *= 10;
cout << counter << endl;
I'v just read about this problem, however I can't find a good solution. Is there really no better way than convert a number to string and count chars? I suppose there's more correct method.
Floating point numbers in computer use binary (base 2, zeros and ones, like almost all numbers in computers). So there is an exact number of binary digits in them, more in double
and less in float
. However, if you convert a decimal constant like 3.141592 to double
, then print it with full accuracy, you don't get same number back. This is because converting the decimals between bases isn't exact in general (it's similar effect effect you get with 1/3 having infinite decimal expansion 0.33...). Example:
double pi = 3.141592;
std::cout << std::setprecision(100) << pi << std::endl;
Outputs for me:
3.14159200000000016217427400988526642322540283203125
So when you start multiplying this by 10 in your question code, you can see how it doesn't become an exact integer in a long time (and by then it is far beyond range of int
), so your condition is never true (either there is fractional part, or the double is too large to fit in integer).
In other words, what you ask, counting digits directly from a double
, makes no sense. You first need to print it as string, otherwise you don't really have a number of decimal digits to count. Of course you could micro-optimize this and skip the actual conversion to ASCII or UTF-16 string, but I don't see a scenario where that would be worth the trouble (except perhaps as a learning excercise).
If you need exact decimal digits in calculations, you need a special number type, which doesn't store fractions in binary. Example of such numeric type is Java BigDecimal.
Atharva MR Fire here.
I've made a simple function that can count number of digits in a double.(float has 8 bits so just change 16 to 8 and make some other necessary changes.)
int get_float_digits(double num)
{
int digits=0;
double ori=num;//storing original number
long num2=num;
while(num2>0)//count no of digits before floating point
{
digits++;
num2=num2/10;
}
if(ori==0)
digits=1;
num=ori;
double no_float;
no_float=ori*(pow(10, (16-digits)));
long long int total=(long long int)no_float;
int no_of_digits, extrazeroes=0;
for(int i=0; i<16; i++)
{
int dig;
dig=total%10;
total=total/10;
if(dig!=0)
break;
else
extrazeroes++;
}
no_of_digits=16-extrazeroes;
return no_of_digits;
}
If you want to get just the number of decimals, add a code no_of_digits=no_of_digits-digits;
at the end, before the return function.
I hope this helps.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With