何かを計算する2つの方法を考えてみましょう:
- 倍精度のデータ
-> 倍精度の一時値を持つ関数を適用
-> 結果を返す - 倍精度のデータ
-> long double にキャスト
-> long double 精度の一時値を持つ関数を適用 ->
double にキャスト
-> 結果を返す
2 番目の解決策は、最初の解決策と比較して精度の低い結果をもたらす可能性がありますか?また、そうである場合はどのような場合ですか?
何かを計算する2つの方法を考えてみましょう:
2 番目の解決策は、最初の解決策と比較して精度の低い結果をもたらす可能性がありますか?また、そうである場合はどのような場合ですか?
はい。証明:c = 0x1p-53+0x1p-64とします。1 + cc-1をdoubleおよびlongdoubleで評価します(一般的なIntel形式で、64ビットの仮数を使用)。doubleの場合、結果は0になります。これは、数学的に正確な答えです。long doubleでは、結果は-0x1p-64になりますが、これは間違っています(doubleにキャストしても間違ったままです)。
ダブルでは、1 + cは1対1のULP(最低精度の単位)の半分より少し多くを追加するので、1プラスULPを生成します。cを引くと、ULPの半分より少し多くが減算されるため、結果に最も近い表現可能な数値(double)は1であるため、1が生成されます。次に、1を引くと0になります。
long doubleでは、1 + cは0x1p-53に1のULPの半分を加えたものを追加します(long doubleでは、1のULPは0x1p-63です)。 double)、下位ビットがゼロの1+0x1p-53が返されます。その場合、cを引いた正確な結果は1-0x1p-64です。これは正確に表現できるので、返されます。最後に、1を引くと-0x1p-64になります。
long double
ドラフトについては次のように述べています。
3.9.1 基本型
8浮動小数点型には、float、double、long double の 3 つがあります。double 型は少なくとも float と同じ精度を提供し、型 long double は少なくとも double と同じ精度を提供します。float 型の値のセットは、double 型の値のセットのサブセットです。double 型の値のセットは、long double 型の値のセットのサブセットです。浮動小数点型の値表現は実装定義です。整数型と浮動小数点型をまとめて算術型と呼びます。標準テンプレート std::numeric_limits (18.3) の特殊化は、実装の各算術型の最大値と最小値を指定するものとします。
次に興味深いプロモーションについては、次のとおりです。
4.6 浮動小数点昇格
1 float 型の prvalue は double 型の prvalue に変換できます。値は変更されません。
2この変換は浮動小数点昇格と呼ばれます。
については何も言われていないことに注意してdouble
くださいlong double
。私はこれをスリップとして危険にさらします。
long double
次に、 からに移動するときに関心のある変換についてdouble
:
4.8 浮動小数点の変換
1浮動小数点型の prvalue は、別の浮動小数点型の prvalue に変換できます。ソース値を変換先の型で正確に表すことができる場合、変換の結果はその正確な表現になります。ソース値が 2 つの隣接する宛先値の間にある場合、変換の結果は、これらの値のいずれかの実装定義の選択になります。それ以外の場合、動作は未定義です。
2浮動小数点昇格として許可された変換は、浮動小数点変換のセットから除外されます。
それでは、ナローイングの効果を見てみましょう:
6 . 縮小変換は暗黙の変換です
[...]
- long double から double または float へ、または double から float へ。ただし、ソースが定数式であり、変換後の実際の値が (正確に表現できない場合でも) 表現できる値の範囲内にある場合を除きます。
このすべての標準から 2 つの要点があります。
long double
が (高いまたは低い) で正確に表すことができない範囲にある場合double
、これらは累積して、別の最終結果を返し、それを として返すことができますdouble
。どちらがより正確かについては、アプリケーションに完全に依存すると思います。