0

Cで精度を落とさずに次の計算をしたい.

uint64_t ts_1 = 0x5212cb03ca115ac0; 
uint64_t ts_2 = 0x5212cb03ca115cc0; 
uint64_t ts_delta = (ts_2 - ts_1)

double scale_factor = ts_delta/(2^32)

ts_delta の値を取得してい0x200.ますが、scale_factor の値は15.000000.基本的に、計算中に精度を失っています。

精度を落とさずに行うにはどうすればよいですか?

これは、私が印刷しようとしている方法に関する短い自己完結型の例です。

#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>

int main()
{
        uint64_t ts_1 = 0x5212cb03ca115ac0;
        uint64_t ts_2 = 0x5212cb03ca115cc0;
        uint64_t ts_delta = (ts_2 - ts_1);
        double scale_factor = ((double)ts_delta) / (((uint64_t)1) << 32);

        printf("ts_delta %"PRIx64" scale factor %f \n",ts_delta,scale_factor);

        return 0;
}
4

2 に答える 2

3

あなたは自分がしていると思う計算をしていません。^Cの演算子は累乗を実行せず、ビット単位の排他的 OR を実行します。あなたは実際に で割っts_deltaてい2 xor 32 == 34ます。どうやってそれを手に入れたのかわかりませんが15.000000、出てきたはず15.058823529411764です。

あなたがやりたかった計算は、次のように C で表現されます。

double scale_factor = ((double)ts_delta) / (((uint64_t)1) << 32);

編集:他の回答から: コンパイラが C99 の 16 進浮動小数点リテラルをサポートしている場合は、次のように書くこともできます。

double scale_factor = ts_delta * 0x1p-32;

このように書くと、キャストは必要ありません。これは、乗算の片側が既に であるdoubleため、反対側の整数が一致するように変換されるためです。uint64_t残念ながら、最近の MSVC など、C99 の他の機能を備えていないコンパイラもいくつかあります。

于 2013-08-28T23:29:10.237 に答える
2

浮動小数点値を計算し、右累乗の式を取得する必要があります。標準機能を使用できますldexp

#include <math.h>

double scale_factor = ldexp(ts_2 - ts_1, -32)

または、定数を掛けるだけです(@Eric Postpischilに感謝します!):

double scale_factor = (ts_2 - ts_1) * 0x1p-32;
于 2013-08-28T23:32:28.010 に答える