I have written a program in C to convert a floating point number represented in binary (1101.11
) into a decimal (13.75
).
However, I cannot seem to get the correct value out of the algorithm.
What is the correct method for converting a binary floating point number into a decimal?
I am using Dev CPP compiler (32 bit). The algorithm is defined below:
void b2d(double p, double q )
{
double rem, dec=0, main, f, i, t=0;
/* integer part operation */
while ( p >= 1 )
{
rem = (int)fmod(p, 10);
p = (int)(p / 10);
dec = dec + rem * pow(2, t);
t++;
}
/* fractional part operation */
t = 1; //assigning '1' to use 't' in new operation
while( q > 0 )
{
main = q * 10;
q = modf(main, &i); //extration of frational part(q) and integer part(i)
dec = dec+i*pow(2, -t);
t++;
}
printf("\nthe decimal value=%lf\n",dec); //prints the final output
}
int main()
{
double bin, a, f;
printf("Enter binary number to convert:\n");
scanf("%lf",&bin);
/* separation of integer part and decimal part */
a = (int)bin;
f = bin - a;
b2d(a, f); // function calling for conversion
getch();
return 0;
}
This piece of code behaves abnormally: I added some simple print statement
When you input 1101.11, the following output shown:
So you got wrong result. I tested
modf
separately with input 1, it gave correct result.So my guess is that you are reading the binary number as double, then tries to convert this double to binary back. There might be something going on under the hood for the precision of number though it shows that it is
1101.11
. As suggested by @Useless, You may need to read the number as a string, figure out the substring before and after the decimal point.
Then convert this two part into decimal separately.You are not, as you believe, reading "1101.11" as a floating point number represented in binary. You are reading it as a base-10 floating point number converted into an IEEE double-precision floating-point value, and then trying to change the base.
The inherent imprecision of this intermediate step is the reason for your problem.
A better approach, as suggested by Vicky, is to:
whole=b1101=13
andnumerator=b11=3
,denominator=4
)whole + numerator/denominator = 13.75
Solution
The following will work as expected:
Output:
Code (
bin2dec.c
):Explanation
The above code works by first finding the index of the decimal point in the number.
Once that is known, it walks the string both backwards and forwards from this index, adding the appropriate value to the
result
variable.The first loop walks backwards from the decimal point and accumulates the powers of 2 if the character is
1
. It takes the distance from the decimal point as the power of two, minus one for the indexing to be correct. Ie, it accumulates :The loop stops when the index reaches the beginning of the string.
The second loop walks forward until the end of the string, and deals with the fractional part as expected it also uses the distance from the index, but this time accumulates fractional parts:
Worked out example:
Beware of malformed input. "10gsh.9701072.67812" will give you a result. It won't mean much :)