Jua*_*tos 9 c++ bitwise-operators
我被要求在C中获取不同类型的内部二进制表示.我的程序目前在'int'中正常工作,但我想用"double"和"float"来使用它.我的代码看起来像这样:
template <typename T>
string findBin(T x) {
string binary;
for(int i = 4096 ; i >= 1; i/=2) {
if((x & i) != 0) binary += "1";
else binary += "0";
}
return binary;
}
Run Code Online (Sandbox Code Playgroud)
当我尝试使用"double"或"float"实例化模板时,程序失败.
Jon*_*ler 16
简而言之,你没有.
当应用于位运算符没有意义double或者float,标准说,位运算符(~,&,|,^,>>,<<,和分配变型)不接受double或float操作数.
双方double并float有3个部分-符号位,指数和尾数.假设你可以转移一个double权利.指数,特别是,这意味着没有简单的平移移位的比特模式右-符号位会移动到指数,和指数的至少显著位将移位到尾数,具有完全非显而易见的集合的含义.在IEEE 754中,在实际尾数位前面有一个隐含的1位,这也使解释复杂化.
类似的注释适用于任何其他位运算符.
因此,由于对double值运算符没有理解或有用的解释,因此标准不允许这些解释.
来自评论:
我只对二进制表示感兴趣.我只是想打印它,而不是做任何有用的东西.
这段代码是几年前为SPARC(大端)架构编写的.
#include <stdio.h>
union u_double
{
double dbl;
char data[sizeof(double)];
};
union u_float
{
float flt;
char data[sizeof(float)];
};
static void dump_float(union u_float f)
{
int exp;
long mant;
printf("32-bit float: sign: %d, ", (f.data[0] & 0x80) >> 7);
exp = ((f.data[0] & 0x7F) << 1) | ((f.data[1] & 0x80) >> 7);
printf("expt: %4d (unbiassed %5d), ", exp, exp - 127);
mant = ((((f.data[1] & 0x7F) << 8) | (f.data[2] & 0xFF)) << 8) | (f.data[3] & 0xFF);
printf("mant: %16ld (0x%06lX)\n", mant, mant);
}
static void dump_double(union u_double d)
{
int exp;
long long mant;
printf("64-bit float: sign: %d, ", (d.data[0] & 0x80) >> 7);
exp = ((d.data[0] & 0x7F) << 4) | ((d.data[1] & 0xF0) >> 4);
printf("expt: %4d (unbiassed %5d), ", exp, exp - 1023);
mant = ((((d.data[1] & 0x0F) << 8) | (d.data[2] & 0xFF)) << 8) | (d.data[3] & 0xFF);
mant = (mant << 32) | ((((((d.data[4] & 0xFF) << 8) | (d.data[5] & 0xFF)) << 8) | (d.data[6] & 0xFF)) << 8) | (d.data[7] & 0xFF);
printf("mant: %16lld (0x%013llX)\n", mant, mant);
}
static void print_value(double v)
{
union u_double d;
union u_float f;
f.flt = v;
d.dbl = v;
printf("SPARC: float/double of %g\n", v);
// image_print(stdout, 0, f.data, sizeof(f.data));
// image_print(stdout, 0, d.data, sizeof(d.data));
dump_float(f);
dump_double(d);
}
int main(void)
{
print_value(+1.0);
print_value(+2.0);
print_value(+3.0);
print_value( 0.0);
print_value(-3.0);
print_value(+3.1415926535897932);
print_value(+1e126);
return(0);
}
Run Code Online (Sandbox Code Playgroud)
注释掉的'image_print()`函数以十六进制打印任意字节集,并进行各种小调整.如果您需要代码,请与我联系(参见我的个人资料).
如果您使用的是英特尔(小端),您可能需要调整代码来处理反向位顺序.但它显示了你如何做到 - 使用一个union.
tem*_*def 10
您不能直接将位运算符应用于float或double,但您仍然可以通过将变量放在union具有适当大小的字符数组的a中来间接访问这些位,然后从这些字符中读取位.例如:
string BitsFromDouble(double value) {
union {
double doubleValue;
char asChars[sizeof(double)];
};
doubleValue = value; // Write to the union
/* Extract the bits. */
string result;
for (size i = 0; i < sizeof(double); ++i)
result += CharToBits(asChars[i]);
return result;
}
Run Code Online (Sandbox Code Playgroud)
你可能需要调整你的例程来处理字符,这些字符通常不超过4096,并且这里也可能有一些古怪的字节序,但基本的想法应该有效.它不是跨平台兼容的,因为机器使用不同的字节序和双精度表示,所以要小心你如何使用它.