我在C中编写了一个程序,将浮点数represented in binary(1101.11
)转换为小数(13.75
)。
但是,我似乎无法从算法中获得正确的值。
将二进制浮点数转换为小数的正确方法是什么?
我正在使用Dev CPP编译器(32位)。该算法定义如下:
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;
}
答案 0 :(得分:4)
你不相信,将“1101.11”读作二进制中表示的浮点数。您正在将其读作 base-10浮点数转换为IEEE双精度浮点值,然后然后尝试更改基数。
这个中间步骤固有的不精确是你的问题的原因。
Vicky建议的更好的方法是:
whole=b1101=13
和numerator=b11=3
,denominator=4
)whole + numerator/denominator = 13.75
答案 1 :(得分:4)
以下内容将按预期工作:
输出:
➤ gcc bin2dec.c -lm -o bin2dec && bin2dec
1101.11 -> 13.750000
1101 -> 13.000000
1101. -> 13.000000
.11 -> 0.750000
代码(bin2dec.c
):
#include <stdio.h>
#include <math.h>
double convert(const char binary[]){
int bi,i;
int len = 0;
int dot = -1;
double result = 0;
for(bi = 0; binary[bi] != '\0'; bi++){
if(binary[bi] == '.'){
dot = bi;
}
len++;
}
if(dot == -1)
dot=len;
for(i = dot; i >= 0 ; i--){
if (binary[i] == '1'){
result += (double) pow(2,(dot-i-1));
}
}
for(i=dot; binary[i] != '\0'; i++){
if (binary[i] == '1'){
result += 1.0/(double) pow(2.0,(double)(i-dot));
}
}
return result;
}
int main()
{
char bin[] = "1101.11";
char bin1[] = "1101";
char bin2[] = "1101.";
char bin3[] = ".11";
printf("%s -> %f\n",bin, convert(bin));
printf("%s -> %f\n",bin1, convert(bin1));
printf("%s -> %f\n",bin2, convert(bin2));
printf("%s -> %f\n",bin3, convert(bin3));
return 0;
}
上面的代码首先找到数字中小数点的索引。
一旦知道了,它就会从该索引向前和向后遍历字符串,并为result
变量添加适当的值。
第一个循环从小数点向后移动,如果字符为1
则累加2的幂。它将小数点的距离作为2的幂,减去索引的正确值。即,它累积:
pow(2,<distance-from-decimal-point>)
当索引到达字符串的开头时,循环停止。
第二个循环向前走直到字符串结束,处理小数部分as expected它也使用距索引的距离,但这次累积了小数部分:
1/pow(2,<distance-from-decimal-point>)
1101.11 = 1101 + 0.11
1101 = 1*2^3 + 1*2^2 + 0*2^1 + 1*2^0 = 8 + 4 + 0 + 1 = 13
0.11 = 1/(2^1) + 1/(2^2) = 0.5 + 0.25 = 0.75
1101.11 = 13.75
小心输入格式错误。 “10gsh.9701072.67812”会给你一个结果。这并不意味着:)
答案 2 :(得分:3)
这段代码表现异常:我添加了一些简单的print语句
while(q>0)
{
double i;
main=q*10.0;
q=modf(main, &i); //extration of frational part(q) and integer part(i)
cout << "main = " << main << " frac part " << q << " int part " << i << endl;
cin.get();
dec=dec+i*pow(2,-t);
t++;
}
输入1101.11时,显示以下输出:
Enter binary number to convert(e.g: 1101.11 which will be 13.75 in decimal):
1101.11
bin in main 1101.11
p 1101 q 0.11
//inside the above while loop code
main = 1.1 frac part 0.1 int part 1
main = 1 frac part 1 int part 0 //^^^^^Error, given main=1, it should output integer part 1, fraction part 0
main = 10 frac part 1 int part 9 //^^^^^same strange error here, it should exit while already
所以你得到了错误的结果。我用输入1分别测试了modf
,它给出了正确的结果。
所以我的猜测是你将二进制数读取为double,然后尝试将此double转换为二进制数。尽管它显示它是1101.11
,但数字的精确度可能会有一些问题。正如@Useless所建议的那样,您可能需要将数字作为字符串读取,找出小数点前后的子字符串.
然后将这两部分分别转换为十进制。