双倍改变一位

时间:2016-05-10 11:03:31

标签: c++ double bit

我试图改变一个双位中的一位,例如:

Double x:-1.500912597,即:

二进制:10111111 11111000 00000011 10111100 11101101 01100100 01001111 10010011

更改基础二进制代码中的一位(例如,位16),以便:

二进制:10111111 11111001 00000011 10111100 11101101 01100100 01001111 10010011

Double x:-1.563412596999999903

我可以使用一些C ++代码吗?

3 个答案:

答案 0 :(得分:1)

#include <ieee754.h>

ieee754_double d = {-1.500912597};
d.ieee.mantissa1 |= 1u << 16; // set bit 16 of mantissa
double x = d.d;

我系统上的标头ieee754.h来自glibc-headers包。

答案 1 :(得分:1)

唯一可移植的方法是使用memcpy(是的,我知道你在想什么,而且不是没有效率)。

请注意,此解决方案不考虑字节顺序。你也需要照顾它,以便严格携带。

#include <cstdlib>
#include <cstring>
#include <utility>
#include <iostream>

// only compile this function if Integer is the same size as a double
template<class Integer, std::enable_if_t<sizeof(Integer) == sizeof(double)>* = nullptr>
double or_bits(double input, Integer bits)
{
  Integer copy;

  // convert the double to a bit representation in the integer 
  std::memcpy(&copy, &input, sizeof(input));
  // perform the bitwise op
  copy |= bits;
  // convert the bits back to a double
  std::memcpy(&input, &copy, sizeof(copy));
  // return the double
  return input;
}

int main()
{
  double d = 1.0;
  d = or_bits(d, 0x10ul);
  std::cout << d << std::endl;
}

gcc5.3上的程序集输出:

double or_bits<unsigned long, (void*)0>(double, unsigned long):
    movq    %xmm0, %rax
    orq     %rdi, %rax
    movq    %rax, -8(%rsp)
    movsd   -8(%rsp), %xmm0
    ret

答案 2 :(得分:0)

位操作有无穷无尽的可能性。所以你应该练习;但我会举几个例子。

下面的代码只会“设置”x的第3位(其中第0位是最低有效位):

#define SET_BIT3 (0x08)
x |= SET_BIT3;

下面的代码只会“重置”第3位:

#define RESET_BIT3 (0xFFFFFFFFFFFFFFF7)
x &= RESET_BIT3;

你可以做的另一件事就是建立一个像这样的联盟:

typedef union
{
    struct
    {
        unsigned BIT0:1;
        unsigned BIT1:1;
        unsigned BIT2:1;
        unsigned BIT3:1;
        unsigned BIT4:1;
        unsigned BIT5:1;
        unsigned BIT6:1;
        unsigned BIT7:1;
        unsigned BIT8:1;
        unsigned BIT9:1;
        unsigned BIT10:1;
        unsigned BIT11:1;
        unsigned BIT12:1;
        unsigned BIT13:1;
        unsigned BIT14:1;
        unsigned BIT15:1;
    };
    struct
    {
        unsigned BYTE0:8;
        unsigned BYTE1:8;
    };
    struct
    {
        unsigned ALL:16;
    };
}two_bytes;

你可以用它做什么:

two_bytes var;

var.ALL = 0; // clear all bits
var.BYTE1 = 0xFF; // make all bits of most significant byte 1
var.BIT7 = 1; // set only bit 7 

或者您可以再次转换为按位运算符:

#define SET_BIT3 (0x08)
var.ALL |= SET_BIT3;