((int64_t)1 << 57) * 100
または* 256
を計算すると、符号付き整数オーバーフローが発生し、コードに未定義の動作が発生します。代わりにuint64_t
とその値を使用した場合、コードは明確に定義されていますが、定義どおりに動作しません。
しかし、ほとんどの場合、この数字を(1 << 63/1.2)
まで上げることは可能です。
がuint64_t
の場合は、元の数を右に32シフトし、最下位の32ビットに(int32_t)(factor * (1 << 8))
を掛けることができます。
次に、乗算の後に8で右シフトしませんが、24で左シフトします。その後、一緒に追加します。
uint64_t apply_uint64_correction(uint64_t y, float32_t factor)
{
uint64_t most_significant = (y >> 32) * (uint32_t)(factor * (1 << 8));
uint64_t least_significant = (y & 0xFFFFFFFFULL) * (uint32_t)(factor * (1 << 8));
return (most_significant << 24) + (least_significant >> 8);
}
さて、apply_uint64_correction(1000000000000, 1.2)
は1199218750000
につながる、とapply_uint64_correction(1000000000000, 1.25)
は1250000000000
ことになります。
あなたがfactor
の範囲を保証することができれば実際にあなたがそれからより多くの精度を行うことができます。
uint64_t apply_uint64_correction(uint64_t y, float32_t factor)
{
uint64_t most_significant = (y >> 32) * (uint32_t)(factor * (1 << 24));
uint64_t least_significant = (y & 0xFFFFFFFFULL) * (uint32_t)(factor * (1 << 24));
return (most_significant << 8) + (least_significant >> 24);
}
apply_uint64_correction(1000000000000, 1.2)
を自分のコンピュータ上1200000047683
を与えるだろう。これは、float32_t
に24ビットの仮数がある場合は、最大精度です。
上記のアルゴリズムは、同様に署名した正の数のために働くだろうが、負の数のために署名したシフトが、私はuint64_t
に値を変換した後、記号のノートを取ると思い灰色の領域であるため、移植性の計算を行います元の符号が負の場合は否定します。
int64_t apply_correction(int64_t y, float32_t factor) {
int negative_result = 0;
uint64_t positive_y = y;
if (y < 0) {
negative_result = 1;
positive_y = -y;
}
uint64_t result = apply_uint64_correction(positive_y, factor);
return negative_result ? -(int64_t)result : result;
}
は 'Y *(int_64t)要因の何が問題なのですか;'? – luk32
@ luk32 'factor 'が0.01-1.2の範囲にあるので、動作しません。 – fluter
倍精度をサポートしていない場合は、そのライブラリを書くか、そこに倍数/倍精度のライブラリをたくさん使うことができます。しかし、倍精度のままでも53ビットの精度しかないので、助けにならないので完全な64ビット精度を得ることはできません –