Extracting a digit from a double value.
Author |
Message |
HazySmoke)345
|
Posted: Sun Apr 01, 2007 12:15 am Post subject: Extracting a digit from a double value. |
|
|
Extracting a digit from a double value:
Let's say that we have a number 1.23456789, and I want the one-hundred-millionths digit from that number (the digit with the 9 in it).
code: | #include <stdio.h>
#include <math.h>
double findDigit(double a, int d){
return floor(fmod (a * pow(10,-d), 10) - fmod (a * pow(10,-d), 1));
}
int main(){
double a;
printf ("%lf", findDigit(1.23456789,-8));
return 0;} |
In the function findDigit, "a" is the number itself, and "d" indicates the digit number. In this case, we use -8 as the "d" value because 10^(-8) is a hundred millionth. So therefore that piece of code should print out the number '9".
Unfortunately, it didn't happen. It printed out the number "8". Is this a problem with the language itself or is it just me? Can someone suggest a way to fix this problem? Thanks. |
|
|
|
|
|
Sponsor Sponsor
|
|
|
klopyrev
|
Posted: Sun Apr 01, 2007 2:58 am Post subject: Re: Extracting a digit from a double value. |
|
|
Unfortunately, its a problem with your programming language. Well, actually, any (or at least those I know of) programming language. The value of a double is stored in binary form in the computer. Thus, what you think is a non-repeating decimal, may actually repeat in binary. For example, you assign the double the number 0.1. It only has one decimal place, but in binary, it has an infinite decimal expansion. If you use your algorithm for finding the digit, the result would be 0, and the next digit would be a 9. The number is actually stored as something like 0.09999...
KL |
|
|
|
|
|
HazySmoke)345
|
Posted: Sun Apr 01, 2007 3:11 am Post subject: Re: Extracting a digit from a double value. |
|
|
Thanks, that helps. (10 bits for you ) I tried to type this code and I see what it's doing now:
code: | int main(){
printf ("%.16lf", 1.23456789);
return 0;} |
The output turned out to be 1.2345678899999999.
Now the 2nd problem. I tried to round that number to the nearest billionth using the following code
code: | int main(){
double a = 1.23456789;
a = floor(a * pow(10,12) + 0.5) / pow(10,12);
printf ("%.16lf",a);
return 0;} |
But it doesn't seem to work, the output still has a whole bunch of 9s at the end. There must be a way to find that digit, right? I mean, the printf function is able to find it. |
|
|
|
|
|
Drakain Zeil
|
Posted: Sun Apr 01, 2007 7:14 am Post subject: RE:Extracting a digit from a double value. |
|
|
Da to string
Sa[n]
or
a=123
(let's get the "3")
floor(a/1)-(floor(a/10)*10)
(let's get the "2")
floor(a/10)-(floor(a/100)*100)
haven't tested, but I remember doing something like this not too long ago. |
|
|
|
|
|
klopyrev
|
Posted: Sun Apr 01, 2007 1:40 pm Post subject: Re: Extracting a digit from a double value. |
|
|
Um... Try this:
double a = 1.23456789
int digit = (int)floor(a*pow(10,8)+0.000001)%10;
Something as simple as that makes it work. You can change the 0.0000001 too. Make it 0.01 or something.
KL |
|
|
|
|
|
OneOffDriveByPoster
|
Posted: Sun Apr 01, 2007 3:41 pm Post subject: Re: Extracting a digit from a double value. |
|
|
HazySmoke)345 @ Sun Apr 01, 2007 12:15 am wrote: Extracting a digit from a double value:
code: | return floor(fmod (a * pow(10,-d), 10) - fmod (a * pow(10,-d), 1));
|
Can someone suggest a way to fix this problem? Thanks.
Don't know if this is better in the general case: c: | return floor(fmod(a, pow(10, d + 1) ) * pow(10, -d) ); |
|
|
|
|
|
|
HazySmoke)345
|
Posted: Sun Apr 01, 2007 8:41 pm Post subject: Re: Extracting a digit from a double value. |
|
|
To klopyrev
Well, that might work. I hate to say it, but I don't seem to like that idea because you're altering the number, which makes it mathematically incorrect. It could work for 1.23456789, but it may not work for some other numbers. Also, if I use a compiler that represents decimals differently, that could cause some serious problems, and I am almost too certain that the printf something doesn't do it that way.
To Drakain
First of all, there's a logic error in your code. When you get the tens digit, the correct code should be
floor(a/10)-(floor(a/100)*10)
And, unfortunately, your source code doesn't really fix the problem The following code printed out the number 8:
code: | int main(){
double a = 1.23456789;
a = floor(a/0.00000001)-(floor(a/0.0000001)*10);
printf ("%lf", a);
return 0;} |
To OneOff
Your source code also returns the value 8 |
|
|
|
|
|
klopyrev
|
Posted: Sun Apr 01, 2007 8:52 pm Post subject: Re: Extracting a digit from a double value. |
|
|
Well, printf just rounds the number to the number of decimal places. If you want the exact printf representation, round the number. If you want the non-rounded digit, use the method I told you about. Anyway, what do you need this for? If you are interested, you can read the guide on floating point numbers on the UVA website. Here's the link: http://acm.uva.es/problemset/float-in-competition.pdf It is very informative, but don't become too paranoid after reading it:P
KL |
|
|
|
|
|
Sponsor Sponsor
|
|
|
HazySmoke)345
|
Posted: Mon Apr 02, 2007 1:13 am Post subject: Re: Extracting a digit from a double value. |
|
|
klopyrev @ Sun Apr 01, 2007 8:52 pm wrote: Well, printf just rounds the number to the number of decimal places. If you want the exact printf representation, round the number.
Yeah, kindly read my first reply of this topic. I've always been trying to do that. I would round it if I could!
But anyway, the website you showed me is nevertheless useful. I wonder if I should ever use double values again... |
|
|
|
|
|
klopyrev
|
Posted: Mon Apr 02, 2007 9:05 am Post subject: Re: Extracting a digit from a double value. |
|
|
Now, when you said you try to round the number to the nearest billionth digit and print out the result, you didn't actually realize what you were doing. Here's what you did. You had the number 1.23456789 stored in the variable. You multiplied it by a power of 10 to get 123456788.99999999999. You added .5 to it to get 123456789.49999999999. You used floor then to get 123456789.000000. Then you shifted the digits again, you thought you got 1.23456789. What you actually got was the original number 1.23456789, because remember, the number 1.23456789 cannot be stored in memory exactly. Therefore - useless code!!! Hope that helps.
KL |
|
|
|
|
|
|
|