8

次のように、16要素のバイト配列から数値(double)値を取得しようとしています。

unsigned char input[16];
double output;
...
double a  = input[0];
distance = a;
for (i=1;i<16;i++){
    a = input[i] << 8*i;
    output += a;
}

しかし、それは機能しません。左シフトの結果を含む一時変数は、8ビットの4シフト操作後にオーバーフローするため、32ビットしか格納できないようです。

私は次のようなものを使用できることを知っています

a = input[i] * pow(2,8*i);

しかし、好奇心のために、シフト演算子を使用してこの問題の解決策があるかどうか疑問に思いました...

4

7 に答える 7

4

編集:これは、のようなものがないと機能しません(コメントを参照)__int128

a = input[i] << 8*i;

式は(6.3.1.1input[i] )にプロモートされます。これは、マシンでは32ビットです。この問題を解決するには、左側のオペランドは次のように64ビットである必要があります。int

a = (1L * input[i]) << 8*i;

また

a = (long long unsigned) input[i] << 8*i;

エンディアンについて覚えておいてください

于 2009-08-19T17:25:18.930 に答える
4

ここでの問題は、実際に32ビット変数を4 * 8回以上シフトできないことです。つまり、コードは4文字でのみ機能します。

あなたができることは、最初の重要な文字を見つけて、ホルネルの法則を使用することです:a n x n + a n-1 n-1 + ... =((...(a n x + a n-1).x + a n-2)。x + ...)+ a0次のように:

char coefficients[16] = { 0, 0, ..., 14, 15 };
int exponent=15;
double result = 0.;

for(int exponent = 15; exp >= 0; --exp ) {
   result *= 256.; // instead of <<8.
   result += coefficients[ exponent ];
}
于 2009-08-19T18:13:39.503 に答える
2

配列を単にダブルポインタにキャストしてみませんか?

unsigned char input[16];

double* pd = (double*)input;

for (int i=0; i<sizeof(input)/sizeof(double); ++i)
    cout << pd[i];

エンディアンを修正する必要がある場合は、double配列にキャストする前に、STL reverse()を使用してchar配列を逆にします。

于 2009-08-20T04:32:23.363 に答える
2

要するに、いいえ、コードサンプルに示されているように、ビットシフトによってbytesのシーケンスを直接aに変換することはできません。double

byte、整数型とdouble、浮動小数点型(つまり整数型ではない)はビット単位の互換性がありません(つまり、一連のバイトの値を浮動小数点型にビットシフトして同等の結果を期待することはできません)。

byte1)バイト配列が整数値を参照するメモリバッファであると仮定すると、ビットシフトを介して配列を128ビット整数に変換し、その結果の整数をに変換できるはずですdouble。CPUアーキテクチャによっては、エンディアンの問題が発生する可能性があることを忘れないでください。

2)バイト配列が128ビットのlong double値を含むメモリバッファであり、エンディアンの問題がないと仮定すると、バイト配列の値をlongdouble値にmemcpyできるはずです。

union doubleOrByte {
    BYTE buffer[16];
    long double val;
} dOrb;
dOrb.val = 3.14159267;
long double newval = 0.0;

memcpy((void*)&newval, (void*)dOrb.buffer, sizeof(dOrb.buffer));
于 2009-08-19T17:25:19.710 に答える
1

std :: atofを試しましたか:

http://www.cplusplus.com/reference/clibrary/cstdlib/atof/

于 2009-08-19T17:18:42.593 に答える
1

数値の文字列表現を実数に変換しようとしていますか?その場合、C標準のatofがあなたの親友です。

于 2009-08-19T17:19:49.940 に答える
0

演算子の優先順位に基づいて、

a = input[i] << 8*i;

doubleに変換される前に評価されるため、input[i]を8* iビットシフトします。これにより、結果が32ビットの一時変数に格納され、オーバーフローします。次のことを試すことができます。

a = (long long unsigned int)input[i] << 8*i;

編集:システムのdoubleのサイズはわかりませんが、私の場合は8バイトです。これが当てはまる場合も、入力配列の後半はシフトがオーバーフローするため、表示されません。ダブルタイプ。

于 2009-08-19T17:17:05.920 に答える