如何在“双”上使用按位运算符。在C ++? [英] How do I use bitwise operators on a "double" on C++?

查看:106
本文介绍了如何在“双”上使用按位运算符。在C ++?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我被要求获得C中不同类型的内部二进制表示。我的程序目前工作正常与'int',但我想使用它与双和浮动。我的代码看起来像这样:

  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;
}

当我尝试使用double

解决方案

确切地说,你不会。



当应用于double或float时,位运算符没有意义。



double和float都有3个部分 - 符号位,指数和尾数。假设有一会儿你可以移动一个双右。特别地,指数意味着没有简单的转换来右移位模式 - 符号位将移动到指数中,并且指数的最低有效位将移位到尾数,具有完全非显而易见的集合意义。在IEEE 754中,在实际尾数位前面有一个隐含的1位,这也使解释复杂化。



类似的注释适用于任何其他位运算符。 / p>

因此,由于对位操作符没有任何理解或有用的解释,因此不允许使用。



< hr>

从注释:


我只对二进制表示感兴趣。


这段代码是几年前写的,用于SPARC(big-endian )架构。

  #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))< (f.data [3]& 0xFF);
printf(mant:%16ld(0x%06lX)\\\
,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))< (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)\\\
,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\\\
,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);
returns(0);
}

注释掉的image_print()`函数打印一组任意字节十六进制,与各种小调整。如果您需要代码(请参阅我的个人资料),请与我联系。



如果您使用的是英特尔(小端),您可能需要调整代码处理反向位顺序。但它显示了你如何做到 - 使用联合


I was asked to get the internal binary representation of different types in C. My program currently works fine with 'int' but I would like to use it with "double" and "float". My code looks like this:

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;
}

The program fails when I try to instantiate the template using a "double" or a "float".

解决方案

Succinctly, you don't.

The bitwise operators do not make sense when applied to double or float.

Both double and float have 3 sections - a sign bit, an exponent, and the mantissa. Suppose for a moment that you could shift a double right. The exponent, in particular, means that there is no simple translation to shifting a bit pattern right - the sign bit would move into the exponent, and the least significant bit of the exponent would shift into the mantissa, with completely non-obvious sets of meanings. In IEEE 754, there's an implied 1 bit in front of the actual mantissa bits, which also complicates the interpretation.

Similar comments apply to any of the other bit operators.

So, because there is no sane or useful interpretation of the bit operators to double values, they are not allowed.


From the comments:

I'm only interested in the binary representation. I just want to print it, not do anything useful with it.

This code was written several years ago for SPARC (big-endian) architecture.

#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);
}

The commented out 'image_print()` function prints an arbitrary set of bytes in hex, with various minor tweaks. Contact me if you want the code (see my profile).

If you're using Intel (little-endian), you'll probably need to tweak the code to deal with the reverse bit order. But it shows how you can do it - using a union.

这篇关于如何在“双”上使用按位运算符。在C ++?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆