c++ - 違い - 浮動小数点 誤差 対策
C/C++で倍精度浮動小数点を使用して転送されたときに浮動小数点が保持されることが保証されていますか? (2)
C99より:
6.3.1.5実浮動型
1 floatがdoubleまたはlong doubleに昇格した場合、またはdoubleがlong doubleに昇格した場合、その値は変更されません。
2 double型が浮動小数点型に降格されるとき、long double型がdouble型またはfloat型に降格されるか、セマンティック型(6.3.1.8参照)よりも高い精度と範囲で表される値がセマンティック型に明示的に変換されます。変換される値は新しい型で正確に表現できますが、変更されません。
私は、float-> double-> float変換が元のfloat値を保持することを保証します。
この規格では、 7.12 Mathematics <math.h>
でマクロINFINITY
とNAN
定義しています。 7.12 Mathematics <math.h>
:
4 INFINITYマクロは、使用可能であれば、正または符号無限大を表すfloat型の定数式に展開されます。 それ以外の場合は、変換時にオーバーフローするfloat型の正の定数になります。
5マクロNANは、実装がfloat型の静かなNaNをサポートしている場合にのみ定義されます。 静かなNaNを表すfloat型の定数式に展開されます。
したがって、そのような特別な値のための規定があり、コンバージョンも同様に(マイナスの無限大と負のゼロを含む)同様に機能するかもしれません。
IEEE-754準拠を前提とすると、doubleを介して転送されたときに保証される浮動小数点数ですか?
言い換えれば、次のような主張は常に満たされるだろうか?
int main()
{
float f = some_random_float();
assert(f == (float)(double)f);
}
f
がIEEEによって定義されたNaNやInfinityなどの特別な値を取得できるとします。
IEEEによれば、アサーションが満たされるケースがありますが、正確なビットレベルの表現は、二重での輸送後も保持されませんか?
コードスニペットは、CとC ++の両方で有効です。
IEEEを想定する必要はありません。 C89は3.1.2.5で言う:
float
型の値のセットは、double
型の値のセットのサブセットです
他のすべてのCおよびC ++標準では同等のことが言われています。 私が知る限り、NaNと無限は「 float
型の値」ですが、オペランドとして使用するときには特殊なルールがいくつかあります。
float - > double - > float変換がfloatの元の値を復元するという事実は、(一般的に)数値変換はすべて、その値がデスティネーション型で表現可能であれば保持されます。
ビットレベル表現はわずかに異なる問題です。 float
値に2つの異なるビット表現があるとします。 それで、Cの標準では、float - > double - > float変換を切り替えることができません。 パディングビットがないかぎり、 "実際の値"に対しては起こらないIEEEでは、IEEEが個別のビット単位の表現を持つ単一のNaNを排除するかどうかはわかりません。 いずれにせよ、NaNはそれ自身と同等ではないので、2つのNaNが文字列に変換されているのではなく、「同じNaN」または「異なるNaN」であるかどうかを判断する標準的な方法もありません。 問題は疑問に思うかもしれません。
注意すべき点の1つは、コンパイルの不適合モードです。たとえば、中間結果を浮動小数点レジスタに残し、丸めを行わずに再利用するなど、非常に正確な値を「カバーする」ことができます。 私はあなたのサンプルコードが失敗する原因になるとは思わないが、浮動小数点を==
とすぐに、あなたが心配し始めるようなものだ。