2017-02-08 55 views
2

我有一個64位數字寫成兩個32位不帶符號整數:unsigned int[2]unsigned int[0]是MSB,而unsigned int[1]是LSB。我如何將它轉換爲double無符號整型[2]?

double d_from_u2(unsigned int*);

+3

你問你如何將你的兩個'unsigned int'的位轉換爲'double',或者「寫爲」對於所需的轉換還有其他含義嗎? –

+0

約翰,只是轉移。 – Danijel

+0

'typedef union {unsigned int iVar [2];雙倍變化; } i2d;'? – KevinDTimm

回答

4

有幾種方式可將兩個整數的比特複製到double類型的對象。

在最低級別,您可以將輸入指針轉換爲[unsigned] char *,創建一個[unsigned] char *的返回值的第一個字節,而那些不擇手段您選擇之間複製。這爲您提供了根據需要調整字節順序的一切機會 - 例如,儘管您的數組首先排序的是最重要的,但這些字中的字節順序可能不是您需要的。

在您需要的字節數的情況下被轉移到你的double最顯著字節在前,而且你不想依賴於機器的字節順序,你可以這樣做:

double d_from_u2(unsigned int *in) { 
    double result; 
    unsigned char *result_bytes = (unsigned char *) &result; 

    for (int i = 0; i < 4; i++) { 
     result_bytes[i] =  in[0] >> (24 - 8 * i); 
     result_bytes[i + 4] = in[1] >> (24 - 8 * i); 
    } 

    return result; 
} 

使用算術(在這種情況下,移位)允許您對輸入的數值進行操作,而與數字表示的細節無關。

5

memcpy它從源陣列,以在適當的順序一個double對象。例如。如果你希望交換的unsigned部分課程

unsigned src[2] = { ... }; 
double dst; 
assert(sizeof dst == sizeof src); 

memcpy(&dst, &src[1], sizeof(unsigned)); 
memcpy((unsigned char *) &dst + sizeof(unsigned), &src[0], sizeof(unsigned)); 

,你永遠可以重新解釋的源和目標對象爲unsigned char陣列和複製它們逐字節任何順序,你希望

unsigned src[2] = { ... }; 
double dst; 

unsigned char *src_bytes = (unsigned char *) src; 
unsigned char *dst_bytes = (unsigned char *) &dst; 

assert(sizeof dst == 8 && sizeof src == 8); 

dst_bytes[0] = src_bytes[7]; 
dst_bytes[1] = src_bytes[6]; 
... 
dst_bytes[7] = src_bytes[0]; 

(第二個例子並不意在等同於第一個。)

+0

不能使用'memcpy',抱歉。 – Danijel

+6

@Danijel:首先,怪問題通常應該在問題中提及......還有什麼「你不能使用」的東西?其次,如果你不能使用'memcpy',你可以明確地手動拼出它。這只是一個複製'n'字節的簡單循環。您甚至可以將其無循環地表示爲逐字節複製。 – AnT

+0

對於答案的正確性並不重要,但我會將'assert'變成'static_assert'(假設C11和所有這些好東西)。 – StoryTeller

0

這裏是一個解決方案,而無需memcpy工作,但使用union

#include "stdio.h" 
#include "stdint.h" 

double d_from_u2(unsigned int* v) { 
    union { 
    int32_t x[2]; 
    int64_t y; 
    } u = { .x = { v[1], v[0] }}; 

    printf("%llu\n", u.y); // 1311768467463794450 

    return (double)u.y; 
} 

int main(void) { 
    int32_t x[2]; 

    x[0] = 0x12345678; 
    x[1] = 0x9abcef12; 
    printf("%f\n", d_from_u2(x)); // 1311768467463794432.000000 
    return 0; 
}  

demo。在初始化聯合中的數組int32_t[2]並使用int64_t將其轉換爲double。初始化的順序取決於它運行的是哪臺機器(小端或大端)或值來自何處(首先是1)。