正确的算法将二进制浮点“1101.11”转换为十进制(13.75)?

我用C编写了一个程序,将二进制 ( 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; } 

这段代码表现exception:我添加了一些简单的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(eg: 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 ,但可能会在数据的精确度下发生一些1101.11 。 正如@Useless所建议的那样,您可能需要将数字作为字符串读取,找出小数点前后的子字符串. 然后将这两部分分别转换为十进制。

正如您所信,您不是将“1101.11”读作二进制表示浮点数 。 您正在将其读作基本10浮点数转换为IEEE双精度浮点值然后尝试更改基数。

这个中间步骤固有的不精确是你的问题的原因。

正如Vicky所建议的那样,更好的方法是:

  1. 将“1101.11”读作字符串或文本行
  2. 转换整数和小数部分( whole=b1101=13numerator=b11=3denominator=4
  3. 将这些重新组合成whole + numerator/denominator = 13.75

以下将按预期工作:

输出:

 ➤ gcc bin2dec.c -lm -o bin2dec && bin2dec 1101.11 -> 13.750000 1101 -> 13.000000 1101. -> 13.000000 .11 -> 0.750000 

代码( bin2dec.c ):

 #include  #include  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,) 

当索引到达字符串的开头时,循环停止。

第二个循环向前走直到字符串结束,并按预期处理小数部分它也使用索引的距离,但这次累积小数部分:

 1/pow(2,) 

算了一些例子:

 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”会给你一个结果。 这并不意味着:)