我正在尝试打印出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;
}
如果我用int a
替换float a
,编译器将无法编译。
有解决方法吗?
复制并重新格式化您的评论
好的,对于那些不清楚的人,我在这里发布我的整个代码:
#include <stdio.h>
#include <stdlib.h>
int bit_return(int a, int loc) // Bit returned at location
{
int buf = a & 1<<loc;
if (buf == 0)
return 0;
else
return 1;
}
int main()
{
int a = 289642; // Represent 'a' in binary
int i = 0;
for (i = 31; i>=0; i--)
{
printf("%d",bit_return(a,i));
}
return 0;
}
答案 0 :(得分:5)
感谢Pascal Cuoq的评论。我终于弄明白了如何解决自己的问题。是的,只需将浮点数的地址分配给指向整数的指针,然后取消引用它。 这是我的代码解决方案:
#include <stdio.h>
// bit returned at location
int bit_return(int a, int loc)
{
int buf = a & 1<<loc;
if (buf == 0) return 0;
else return 1;
}
int main()
{
//11000010111011010100000000000000
// 1 sign bit | 8 exponent bit | 23 fraction bits
float a = -118.625;
int *b;
b = &a;
int i;
for (i = 31; i >= 0; i--)
{
printf("%d",bit_return(*b,i));
}
return 0;
}
答案 1 :(得分:4)
将float的地址转换为相同大小的int的地址,并将该int传递给现有函数。
答案 2 :(得分:3)
在C语言中,术语“位”是指数字的二进制位置表示的元素。 C中的积分数使用二进制位置表示,这就是它们具有“位”的原因。这些是您通过按位运算符(逻辑和移位)“看到”的位。浮点数不使用该表示。此外,浮点数的表示不是由语言规范定义的,换句话说,C中的浮点数没有“位”,这就是为什么你不能通过语言的任何合法方式访问它们的任何“位”,这就是为什么你不能将任何按位运算符应用于浮点对象的原因。
话虽如此,我怀疑您可能对表示浮点对象的物理位感兴趣。您可以将浮点对象(或任何其他对象)占用的内存重新解释为unsigned char
元素的数组,并打印每个unsigned char
对象的位。这将为您提供表示对象的所有物理位的映射。
但是,这与上面代码中的内容不完全相同。上面的代码打印了一个整数对象的值表示位(即它是我上面描述的逻辑位),而内存重新解释方法会给你一些位对象表示(即物理位)。但话说回来,C中的浮点数根据定义没有逻辑位。
稍后添加:我觉得理解物理位和逻辑位概念之间的差异对于某些读者来说可能不是一件容易的事。作为另一个可能有助于促进理解的例子,我想指出,绝对没有什么能阻止三元硬件上完全兼容的C实现,即没有物理二进制位的硬件所有。在这样的实现中,按位操作仍然可以完美地工作,它们仍然可以访问二进制位,即每个整数的[现在只是虚构的]二进制位置表示的元素。那就是我上面谈到的逻辑位。
答案 3 :(得分:3)
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&amp; R C与ANSI C问题。更新: 二进制输出...
while (n > 0) {
int q;
--n;
for(q = 0x80; q; q >>= 1)
printf("%x", !!(t[n] & q));
}
答案 4 :(得分:2)
以下代码假定浮点数和指针大小相同,在许多系统上都是如此:
float myfloat = 254940.4394f;
printf("0x%p", *(void**)(&myfloat));
答案 5 :(得分:2)
虽然从注释中看来,输出内部表示的位可能是想要的,但这里的代码可以解决问题似乎真正要求的问题,而不是有些人提议将有损转换为int:
以二进制形式输出浮点数:
#include <stdio.h>
#include <stdlib.h>
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;
}
答案 6 :(得分:1)
如果你想在浮点数上使用你的bit_return函数,你可以欺骗:
float f = 42.69;
for ....
bit_return((int) f, loc)
(int)强制转换将使编译器相信您正在使用整数,因此bit_return将起作用。
这基本上是帕斯卡所暗示的。
修改强>
Pascal纠正了我的观点。我认为这符合他最新的评论:
bit_return (*((float *) &f), loc)
希望我能在那个时候做对。
另一种选择(括号较少)是使用 union 来欺骗数据类型。
答案 7 :(得分:1)
我已经包含了生成十六进制输出的代码,我认为这可能有助于您理解浮点数。这是一个例子:
double:00 00 A4 0F 0D 4B 72 42(1257096936000.000000)(+ 0x1.24B0D0FA40000 x 2 ^ 40)
从下面的代码示例中,您应该明白如何输出这些位。将双精度地址转换为unsigned char *
并输出sizeof(double)
个字符的位。
由于我想输出浮点数的指数和有效数(和符号位),我的示例代码深入研究了IEEE-754标准表示的64位“双精度”浮动指向点的位基数2.因此我不使用sizeof(double)
来验证编译器和我同意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:有效数显示为十六进制分数(“0x1.24B0D0FA40000”),指数显示为十进制(“40”)。对我来说,这是一种显示浮点位的直观方式。
答案 8 :(得分:0)
打印整数部分,然后打印'。',然后打印小数部分。
float f = ...
int int_part = floor(f)
int fraction_part = floor((f - int_part) * pow(2.0, 32))
然后,您可以使用bit_return打印x和y。不打印前导零和/或尾随零的加分点。