一般原則として、paxdiabloの回答には関連する部分が含まれています。ほとんどの終了小数は、2進浮動小数点数として正確に表すことができないため、浮動小数点変数の値は、指定された文字列の数値表現の数学値よりも少し小さいか大きいため、適切な整数を取得する場合スケーリング後の値は、切り捨てではなく丸める必要があります。
しかし、ここでの特定の例では、別のシナリオがあります。1441.1441に最も近いIEEE754倍精度(64ビットバイナリ)値は次のとおりです。
1441.14409999999998035491444170475006103515625
これは確かに1441.1441より少し小さいです。ただし、その値にIEEE754倍精度値として10000を掛けると、結果は正確になります。
14411441
ここで何が起こるかというと、5.2.4.2.2パラグラフ9で許可されているように
代入とキャスト(余分な範囲と精度をすべて削除する)を除いて、浮動オペランドと通常の算術変換の対象となる値を持つ演算子と浮動定数によって生成される値は、範囲と精度がタイプ。
(強調鉱山)、製品はタイプ(おそらくx87 80ビット形式)で必要とされるよりも高い精度で評価され、わずかに小さい値が生成され、乗算の結果がに変換されるint
と、小数部分は破棄されます、および14411440を取得します。
scanf("%lf",&num);
値はに格納されるnum
ため、精度は正確に。である必要がありdouble
ます。
tmp=num*10000;
製品num * 10000
は保存もキャストもされないdouble
ため、精度が高くなり、最も近い値よりも小さい値または大きい値になる可能性がありdouble
ます。次に、その値が切り捨てられて。が取得されint
ます。
double
製品を変数に保存した場合
num *= 10000;
tmp = num;
double
または、に変換する前にキャストしますint
。
tmp = (double)(num * 10000);
入力の結果14411441を取得する必要があります1441.1441
(ただし、すべてのコンパイラが、キャストまたは保存時に必要な正確な精度に変換する要件を常に満たすわけではないことに注意してください-標準に違反しています-したがって、すべての最適化設定で14411441が生成される保証はありません)。
多くの64ビットプラットフォームは、x87コプロセッサーではなくSSE命令を使用して浮動小数点演算を実行するため、観察された動作は、32ビットシステムよりも64ビットシステムで発生する可能性が低くなります。