简体   繁体   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

the code that hands me the two uint32_t essentially takes a double, in binary cuts it in half so half the bytes are in one variable and the other half are in the other.交给我两个 uint32_t 的代码本质上是一个双精度,二进制将它切成两半,所以一半的字节在一个变量中,另一半在另一个变量中。

My program need to take them and stitch it back together.我的程序需要把它们拼接起来。

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

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

this is what i have so far and it doesnt give the correct output at all.这是我到目前为止所拥有的,它根本没有给出正确的 output。

it gives: 1.84467e+19 it should be: 6.49999999999999952595094363798E-11它给出:1.84467e+19 它应该是:6.49999999999999952595094363798E-11

Thanks谢谢

For C, you can do it this way:对于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);

But I'm not sure, there could be an endian issue here since this code is quite hairy.但我不确定,这里可能存在字节顺序问题,因为这段代码非常多毛。 I'm getting 6.5e-11 as the output.我得到 6.5e-11 作为 output。

This works:这有效:

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!

Your code had two problems:您的代码有两个问题:

  • the signed integer y was being converted to long long , which meant that the high word was 0xFFFFFFFF .签名的 integer y被转换为long long ,这意味着高位字是0xFFFFFFFF x and y should be declared unsigned . xy应声明为unsigned
  • static_cast converts the value, not the bit pattern. static_cast转换值,而不是位模式。 Use reinterpret_cast to retain the bit pattern.使用reinterpret_cast保留位模式。 (As Mgetz points out in a comment, there is now (since C++20) an official way to get this done: std::bit_cast . This doesn't rely on undefined behaviour, as long as double and int64 are the same size.) (正如 Mgetz 在评论中指出的那样,现在(自 C++20 起)有一种官方方法可以完成此操作: std::bit_cast 。这不依赖于未定义的行为,只要doubleint64相同尺寸。)

How about this code for your purpose.这段代码如何满足您的目的。 example例子

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

solution to your problem解决你的问题

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

}

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

or without referencing problem或者没有引用问题

#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.

相关问题 将包含 32 位值的 uint64_t 传递给参数实际上是 uint32_t 的外部 function 是否安全? - Is it safe to pass a uint64_t containing a 32-bit value to an external function whose parameter is actually a uint32_t? 在 C++20 中输入双关 uint64_t 作为两个 uint32_t - Type-pun uint64_t as two uint32_t in C++20 将uint32_t转换为uint64_t导致不同的值? - casting uint32_t to uint64_t results in different value? 将uint64_t rdtsc值转换为uint32_t - Converting a uint64_t rdtsc value to a uint32_t 为什么在 64 位机器上使用 uint8_t 编写的这段代码比使用 uint32_t 或 uint64_t 编写的类似代码运行得更快? - Why does this piece of code written using uint8_t run faster than analogous code written with uint32_t or uint64_t on a 64bit machine? 如何以类型安全的方式分配uint32_t :: max和uint64_t的最小值? - How to assign min of uint32_t::max and uint64_t in type safe manner? 使用多个uint32_t整数生成uint64_t哈希键 - Generate uint64_t hash key with several uint32_t integers 在 uint32_t 范围内变换 uint64_t 范围 - Transform uint64_t range in uint32_t range 如何将 uint32_t 或 uint64_t 存储在 void 指针中 - How can I store a uint32_t or uint64_t in a void pointer 如何让gcc警告从uint32_t到uint64_t的转换? - How to have gcc warn about conversions from uint32_t to uint64_t?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM