繁体   English   中英

将两个 uint32_t 转换为 uint64_t,然后根据位模式而不是值转换回 double

[英]Turn two uint32_t into a uint64_t, then turn back into a double based on the bit pattern not the value

交给我两个 uint32_t 的代码本质上是一个双精度,二进制将它切成两半,所以一半的字节在一个变量中,另一半在另一个变量中。

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

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

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

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

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

谢谢

对于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 作为 output。

这有效:

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!

您的代码有两个问题:

  • 签名的 integer y被转换为long long ,这意味着高位字是0xFFFFFFFF xy应声明为unsigned
  • static_cast转换值,而不是位模式。 使用reinterpret_cast保留位模式。 (正如 Mgetz 在评论中指出的那样,现在(自 C++20 起)有一种官方方法可以完成此操作: std::bit_cast 。这不依赖于未定义的行为,只要doubleint64相同尺寸。)

这段代码如何满足您的目的。 例子

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM