如何打印浮点数的每一位?

我试图在C中打印出浮点数的每一位。

我可以用这个整数做到这一点:

int bit_return(int a, int loc) // Bit returned at location { int buf = a & 1<<loc; if (buf == 0) return 0; else return 1; } 

如果我用float a替换int a ,编译器将无法编译。

这有解决方案吗?


复制并重新格式化您的评论如下

好的,对于不清楚的人,我在这里发布我的整个代码:

 #include  #include  int bit_return(int a, int loc) // Bit returned at location { int buf = a & 1<=0; i--) { printf("%d",bit_return(a,i)); } return 0; } 

感谢Pascal Cuoq的评论。 我终于弄清楚如何解决自己的问题。 是的,只需将浮点数的地址分配给指向整数的指针,然后取消引用它。 这是我的代码解决方案:

 #include  // bit returned at location int bit_return(int a, int loc) { int buf = a & 1<= 0; i--) { printf("%d",bit_return(*b,i)); } return 0; } 

将float的地址转换为相同大小的int的地址,并将该int传递给现有函数。

 static void printme(void *c, size_t n) { unsigned char *t = c; if (c == NULL) return; while (n > 0) { --n; printf("%02x", t[n]); } printf("\n"); } void fpp(float f, double d) { printme(&f, sizeof f); printme(&d, sizeof d); } 
  • 关于float参数的注释

    当你调用它时,请确保你在范围内有fpp()的原型,否则你将调用一个模糊的K&R C与ANSI C问题。

更新:二进制输出…

  while (n > 0) { int q; --n; for(q = 0x80; q; q >>= 1) printf("%x", !!(t[n] & q)); } 

在C语言中,术语“位”指的是数字的二进制位置表示的元素。 C中的积分数使用二进制位置表示,这就是它们具有“位”的原因。 这些是您通过按位运算符(逻辑和移位)“看到”的位。 浮点数不使用该表示。 此外,浮点数的表示不是由语言规范定义的,换句话说, C中的浮点数没有“位” ,这就是为什么你将无法访问它们的任何“位”的原因。通过该语言的任何合法方式,这就是为什么你不能将任何按位运算符应用于浮点对象。

话虽如此,我怀疑你可能对代表浮点对象的物理位感兴趣。 您可以将浮点对象(或任何其他对象)占用的内存重新解释为unsigned char元素数组,并打印每个unsigned char对象的位。 这将为您提供表示对象的所有物理位的映射。

但是,这不会完全等同于上面代码中的内容。 上面的代码打印了一个整数对象的值表示位(即它是我上面描述的逻辑位),而内存重新解释方法将为您提供对象表示的位(即物理位)。 但话说回来,C中的浮点数根据定义没有逻辑位。

稍后补充:我觉得理解物理位和逻辑位概念之间的差异对于某些读者来说可能不是一件容易的事。 作为另一个可能有助于促进理解的例子,我想指出,绝对没有任何东西可以排除三元硬件上完全兼容的C实现,即根本没有物理二进制位的硬件。 在这样的实现中,按位操作仍然可以完美地工作,它们仍将访问二进制位,即每个整数的[现在只是虚构的]二进制位置表示的元素。 那将是我上面谈到的逻辑比特。

以下代码假定浮点数和指针大小相同,在许多系统上都是如此:

 float myfloat = 254940.4394f; printf("0x%p", *(void**)(&myfloat)); 

从注释看来,输出内部表示的位可能是想要的,这里是代码来执行问题似乎字面上要求的,没有有人提出的有损转换为int:

以二进制forms输出浮点数:

 #include  #include  void output_binary_fp_number(double arg) { double pow2; if ( arg < 0 ) { putchar('-'); arg = -arg; } if ( arg - arg != 0 ) { printf("Inf"); } else { /* compare and subtract descending powers of two, printing a binary digit for each */ /* first figure out where to start */ for ( pow2 = 1; pow2 * 2 <= arg; pow2 *= 2 ) ; while ( arg != 0 || pow2 >= 1 ) { if ( pow2 == .5 ) putchar('.'); if ( arg < pow2 ) putchar('0'); else { putchar('1'); arg -= pow2; } pow2 *= .5; } } putchar('\n'); return; } void usage(char *progname) { fprintf(stderr, "Usage: %s real-number\n", progname); exit(EXIT_FAILURE); } int main(int argc, char **argv) { double arg; char *endp; if ( argc != 2 ) usage(argv[0]); arg = strtod(argv[1], &endp); if ( endp == argv[1] || *endp ) usage(argv[0]); output_binary_fp_number(arg); return EXIT_SUCCESS; } 

如果你想在浮点数上使用你的bit_return函数,你可以欺骗:

 float f = 42.69; for .... bit_return((int) f, loc) 

(int)强制转换将使编译器相信您正在使用整数,因此bit_return将起作用。

这基本上是帕斯卡所暗示的。

编辑:

Pascal纠正了我的观点。 我认为这符合他的最新评论:

 bit_return (*((float *) &f), loc) 

希望我能在那个时候做对。

另一种选择(括号较少)是使用联合来欺骗数据类型。

我已经包含了生成hex输出的代码,我认为这可能有助于您理解浮点数。 这是一个例子:

double:00 00 A4 0F 0D 4B 72 42(1257096936000.000000)(+ 0x1.24B0D0FA40000 x 2 ^ 40)

从下面的代码示例中,您应该明白如何输出位。 将double的地址转换为unsigned char *并输出sizeof(double)字符的位。

由于我想输出浮点数的指数和有效数(和符号位),我的示例代码深入研究了基数2中64位“双精度”浮点指针点的IEEE-754标准表示的位。因此我不使用sizeof(double)来validation编译器和我同意double意味着64位浮点数。

如果要输出任何类型的浮点数的位,请使用sizeof(double)而不是8

 void hexdump_ieee754_double_x86(double dbl) { LONGLONG ll = 0; char * pch = (char *)≪ int i; int exponent = 0; assert(8 == sizeof(dbl)); // Extract the 11-bit exponent, and apply the 'bias' of 0x3FF. exponent = (((((char *)&(dbl))[7] & 0x7F) << 4) + ((((char *)&(dbl))[6] & 0xF0) >> 4) & 0x7FF) - 0x3FF; // Copy the 52-bit significand to an integer we will later display for (i = 0; i < 6; i ++) *pch++ = ((char *)&(dbl))[i]; *pch++ = ((char *)&(dbl))[6] & 0xF; printf("double: %02X %02X %02X %02X %02X %02X %02X %02X (%f)", ((unsigned char *)&(dbl))[0], ((unsigned char *)&(dbl))[1], ((unsigned char *)&(dbl))[2], ((unsigned char *)&(dbl))[3], ((unsigned char *)&(dbl))[4], ((unsigned char *)&(dbl))[5], ((unsigned char *)&(dbl))[6], ((unsigned char *)&(dbl))[7], dbl); printf( "\t(%c0x1.%05X%08X x 2^%d)\n", (((char *)&(dbl))[6] & 0x80) ? '-' : '+', (DWORD)((ll & 0xFFFFFFFF00000000LL) >> 32), (DWORD)(ll & 0xFFFFFFFFLL), exponent); } 

Nota Bene:有效数显示为hex分数(“0x1.24B0D0FA40000”),指数显示为十进制(“40”)。 对我来说,这是一种显示浮点位的直观方式。

打印整数部分,然后打印’。’,然后打印小数部分。

 float f = ... int int_part = floor(f) int fraction_part = floor((f - int_part) * pow(2.0, 32)) 

然后,您可以使用bit_return打印x和y。 不打印前导零和/或尾随零的加分点。