在C ++中获取double的精确位表示

时间:2015-08-27 21:45:58

标签: c++ hash types hashtable bit

让我们说我们有一个双,比如,x = 4.3241;

很简单,我想知道,在C ++中,如何只能在数字表示中为每个位检索一个int?

我见过其他questions并阅读了bitset上的页面,但我恐怕还是不明白如何检索这些位。

所以,例如,我希望输入为x = 4.53,如果位表示为10010101,那么我想要8个整数,每个整数代表每个1或者0

2 个答案:

答案 0 :(得分:7)

类似的东西:

double doubleValue = ...whatever...;
uint8_t *bytePointer = (uint8_t *)&doubleValue;

for(size_t index = 0; index < sizeof(double); index++)
{
    uint8_t byte = bytePointer[index];

    for(int bit = 0; bit < 8; bit++)
    {
        printf("%d", byte&1);
        byte >>= 1;
    }
}

...将打印出来的位,从字节中的最低有效位到最高有效位排序,并从头到尾读取字节。根据您的机器架构,这意味着字节可能或可能不是重要的顺序。英特尔是严格的小端,所以你应该从最不重要到最重要的所有位;大多数CPU对浮点数使用与整数相同的字节顺序,但即使这样也不能保证。

只需分配一个数组并存储这些位而不是打印它们。

(假设:一个字节中有8位;在技术上没有保证在C中,但在现在可能遇到的任何硬件上相当可靠)

答案 1 :(得分:4)

这非常依赖于架构。收集以下信息后

  1. 目标架构的Endianess
  2. 浮点表示(例如IEEE754
  3. double类型
  4. 的大小

    您应该能够获得您正在搜索的位代表。在x86_64系统上测试的示例

    #include <iostream>
    #include <climits>
    
    int main()
    {
      double v = 72.4;
    
      // Boilerplate to circumvent the fact bitwise operators can't be applied to double
      union {
        double value;
        char   array[sizeof(double)];
      };
    
      value = v;
    
      for (int i = 0; i < sizeof(double) * CHAR_BIT; ++i) {
        int relativeToByte = i % CHAR_BIT;
        bool isBitSet = (array[sizeof(double) - 1 - i / CHAR_BIT] & 
           (1 << (CHAR_BIT - relativeToByte - 1))) == (1 << (CHAR_BIT - relativeToByte - 1));
        std::cout << (isBitSet ? "1" : "0");
      }
      return 0;
    }
    

    Live Example

    输出

    0100000001010010000110011001100110011001100110011001100110011010
    

    分为signexponentsignificand(或尾数),

    0 10000000101 (1.)0010000110011001100110011001100110011001100110011010
    

    enter image description here (图片取自wikipedia

    无论如何,你需要知道你的目标表示是如何工作的,否则这些数字对你来说几乎没用。

    由于你的问题不清楚你是否希望那些整数按照你的数字的内部表示有意义的顺序,只是在遇到它们时转储那个地址的字节,我就加入了另一种更简单的方法就是转储该地址的每个字节(并显示处理位运算符和double的另一种方法)

    double v = 72.4;
    
    uint8_t *array = reinterpret_cast<uint8_t*>(&v);
    
    for (int i = 0; i < sizeof(double); ++i) {
      uint8_t byte = array[i];
      for (int bit = CHAR_BIT - 1; bit >= 0; --bit) // Print each byte
        std::cout << ((byte & (1 << bit)) == (1 << bit));
    }
    

    上面的代码只是将每个字节从较低地址的字节打印到具有较高地址的字节。

    编辑:因为你似乎只对那里有多少1和0感兴趣(即顺序完全不重要),在这个特定的例子中我同意其他答案,我也会只是去寻找一个计数解决方案

    uint8_t *array = reinterpret_cast<uint8_t*>(&v);
    
    for (int i = 0; i < sizeof(double); ++i) {
      uint8_t byte = array[i];
      for (int j = 0; j < CHAR_BIT; ++j) {
        std::cout << (byte & 0x1);
        byte >>= 1;
      }
    }