2017-02-08 18 views
2

私は、2つの32ビットのunsinged int:unsigned int[2]として書かれた64ビットの数値を持っています。 unsigned int[0]はMSB、unsigned int[1]はLSBです。どのように私はそれをdoubleに変換するでしょうか?ダブルからunsigned int [2]?

double d_from_u2(unsigned int*);

+3

2つの 'unsigned int 'のビットを' double'に転送する方法を尋ねていますか、または「written as」は必要な変換に何か意味がありますか? –

+0

ジョン、ちょうど転送します。 – Danijel

+0

'typedef union {unsigned int iVar [2];ダブルdVar; } i2d; '? – KevinDTimm

答えて

4

2つの整数のビットをdoubleのオブジェクトにコピーする方法はいくつかあります。最低レベルでは

、あなたは、戻り値の最初のバイトに[unsigned] char *を作成し、あなたが選択したあらゆる手段によって、それらの間でコピーし、[unsigned] char *にご入力ポインタを変換することができます。これにより、必要に応じてバイトオーダーを調整する機会がすべて提供されます。たとえば、配列が最も重要な順序で配列されていますが、ワードが最初に必要です。

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

:あなたはバイトが最初にあなたのdouble最上位バイトに転送されるように、そしてあなたは、マシンバイト順序に依存しないことを、あなたがこれを行う可能性があります必要がある場合は

算術演算(この場合はシフト)を使用すると、数値表現の詳細とは独立して入力の数値を操作することができます。ここで

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 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]; 
を希望する任意の順序でバイトごとに unsigned charの配列として送信元と宛先の両方のオブジェクトを再解釈し、それらをコピーすることができます

(2番目の例は、最初の例と同じではありません)

+0

'memcpy'は使用できません。申し訳ありません。 – Danijel

+6

@ダニエル:まず、質問には奇妙な制限が言及されるべきです...あなたが「使用できない」ことが他にありますか?第二に、 'memcpy'を使うことができない場合は、明示的に手動で明示的に記述することができます。 'n'バイトをコピーするだけの単純なサイクルです。サイクルなしで、バイト単位のコピーとして表現することもできます。 – AnT

+0

答えの正しさは本当に重要ではありませんが、私は 'assert'を' static_assert'(C11とすべての良いものを前提としています)にします。 – StoryTeller

0

unionを使用してmemcpyせずに動作しますが、解決策です:

#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を参照してください。 Inは、ユニオン内の配列int32_t[2]を初期化し、int64_tを使用してdoubleに変換します。初期化の順序は、実行するマシン(リトルエンディアンまたはビッグエンディアン)、または値がどこから来るかによって異なります(1最初)。

関連する問題