【问题标题】:Turn two uint32_t into a uint64_t, then turn back into a double based on the bit pattern not the value将两个 uint32_t 转换为 uint64_t,然后根据位模式而不是值转换回双精度
【发布时间】:2018-04-21 05:24:48
【问题描述】:

将两个 uint32_t 交给我的代码实际上需要一个双精度数,在二进制中将其切成两半,因此一半字节在一个变量中,另一半在另一个变量中。

我的程序需要将它们拼接起来。

int x = 0b00111101110100011101110111110111;
int y = 0b11100111001100101010000110111001;

uint64_t int64 = (long long) x << 32 | y;
double d = static_cast<double> (int64);

这是我到目前为止所拥有的,它根本没有给出正确的输出。

它给出:1.84467e+19 它应该是:6.49999999999999952595094363798E-11

谢谢

【问题讨论】:

  • 那么你得到的错误输出是什么??
  • 你可能想要static_assert(sizeof(double) == sizeof(uint64_t), "!"); memcpy(&amp;d, &amp;int64, sizeof(double));
  • 您也不想在c 中使用static_cast。所以我删除了那个标签。
  • 你不想做一个 static_cast,因为它会尝试将“int64”中的整数值转换为浮点值。相反,请使用 memcpy。

标签: c++ qt c++11 c++14


【解决方案1】:

对于 C,你可以这样做:

const uint32_t x = 0x3DD1DDF7;
const uint32_t y = 0xE732A1B9;
const uint64_t z = ((uint64_t) x << 32) | y;
double d;
memcpy(&d, &z, sizeof d);

但我不确定,这里可能存在字节序问题,因为这段代码很麻烦。我得到 6.5e-11 作为输出。

【讨论】:

    【解决方案2】:

    这行得通:

    unsigned int x = 0b00111101110100011101110111110111;
    unsigned int y = 0b11100111001100101010000110111001; // Must be unsigned!
    
    uint64_t int64 = ((long long) x << 32) | y; // Parentheses highly recommended for
                                                // readability (but not strictly necessary)
    double d = reinterpret_cast<double&> (int64); // Definitely not portable!
    

    您的代码有两个问题:

    • 有符号整数y 被转换为long long,这意味着高位字是0xFFFFFFFFxy 应声明为 unsigned
    • static_cast 转换值,而不是位模式。使用reinterpret_cast 保留位模式。 (正如 Mgetz 在评论中指出的那样,现在(从 C++20 开始)有一种正式的方式来完成这项工作:std::bit_cast。这不依赖于未定义的行为,只要 doubleint64大小相同。)

    【讨论】:

      【解决方案3】:

      如何根据您的目的使用此代码。例子

      #include <cstdio>
      #include <cinttypes>
      #include <type_traits>
      #include <cstddef>
      #include <iostream>
      
      int main()
      {
          uint64_t tsc = 0xdeaddeadc0dec0de;
          uint32_t MSB = *((uint32_t*)&tsc+1);
          uint32_t LSB = *((uint32_t*)&tsc);
          std::printf("low   %x high %x \n", LSB,MSB);
          uint64_t MLSB = 0;
          *((uint32_t*)&MLSB) = LSB;
          *((uint32_t*)&MLSB+1) = MSB;
          std::printf("highlow %lx \n", MLSB);
          uint64_t LMSB = 0;
          *((uint32_t*)&LMSB+1) = LSB;
          *((uint32_t*)&LMSB) = MSB;
          std::printf("lowhigh %lx \n", LMSB);
      }
      

      解决您的问题

      #include <cstdio>
      #include <cinttypes>
      #include <type_traits>
      #include <cstddef>
      #include <iostream>
      
      int main()
      {
      int x = 0b01000000001101110000000000000000;
      int y = 0b00000000000000000000000000000000;
          uint64_t int64 = 0;
          *((uint32_t*)&int64+1) = x;
          *((uint32_t*)&int64) = y;
          double d = *((double*)&int64);
          std::printf("double d %e \n", d);
          std::printf("int int64 %llx \n", int64);
          
      x = 0b00111101110100011101110111110111;
      y = 0b11100111001100101010000110111001;
          *((uint32_t*)&int64+1) = x;
          *((uint32_t*)&int64) = y;
          d = *((double*)&int64);
          std::printf("double d %e \n", d);
          std::printf("int int64 %llx \n", int64);
      
      }
      

      结果
      双 d 2.300000e+01
      int int64 4037000000000000
      双 d 6.500000e-11
      int int64 3dd1ddf7e732a1b9

      或者没有引用问题

      #include <cstdio>
      #include <cinttypes>
      #include <type_traits>
      #include <cstddef>
      #include <iostream>
      
      int main()
      {
      unsigned char  x[] = {0b01000000,0b00110111,0b00000000,0b00000000};
      unsigned char  y[] = {0b00000000,0b00000000,0b00000000,0b00000000};
          uint64_t int64 = 0;
          *((unsigned char*)&int64+7) = x[0];
          *((unsigned char*)&int64+6) = x[1];
          *((unsigned char*)&int64+5) = x[2];
          *((unsigned char*)&int64+4) = x[3];
          *((unsigned char*)&int64+3) = y[0];
          *((unsigned char*)&int64+2) = y[1];
          *((unsigned char*)&int64+1) = y[2];
          *((unsigned char*)&int64+0) = y[3];
          double d =0;
          *((unsigned char*)&d+7) = x[0];
          *((unsigned char*)&d+6) = x[1];
          *((unsigned char*)&d+5) = x[2];
          *((unsigned char*)&d+4) = x[3];
          *((unsigned char*)&d+3) = y[0];
          *((unsigned char*)&d+2) = y[1];
          *((unsigned char*)&d+1) = y[2];
          *((unsigned char*)&d+0) = y[3];
          //*((double*)&int64);
          std::printf("double d %e \n", d);
          std::printf("int int64 %lu \n", int64);
          
      }
      

      【讨论】:

        猜你喜欢
        • 2021-09-12
        • 2023-04-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-24
        • 1970-01-01
        • 2010-10-16
        • 2012-09-23
        相关资源
        最近更新 更多