補間関数の 2 つの実装を次に示します。引数u1
は常に ~ の間0.
です1.
。
#include <stdio.h>
double interpol_64(double u1, double u2, double u3)
{
return u2 * (1.0 - u1) + u1 * u3;
}
double interpol_80(double u1, double u2, double u3)
{
return u2 * (1.0 - (long double)u1) + u1 * (long double)u3;
}
int main()
{
double y64,y80,u1,u2,u3;
u1 = 0.025;
u2 = 0.195;
u3 = 0.195;
y64 = interpol_64(u1, u2, u3);
y80 = interpol_80(u1, u2, u3);
printf("u2: %a\ny64:%a\ny80:%a\n", u2, y64, y80);
}
80 ビットlong double
s を使用する厳密な IEEE 754 プラットフォームでは、 のすべての計算はinterpol_64()
IEEE 754 の倍精度に従って行われinterpol_80()
、80 ビットの拡張精度で行われます。プログラムは次を出力します。
u2: 0x1.8f5c28f5c28f6p-3
y64:0x1.8f5c28f5c28f5p-3
y80:0x1.8f5c28f5c28f6p-3
「関数が返す結果は常に と の間」という性質に興味がありu2
ますu3
。interpol_64()
上記の値が示すように、このプロパティは の false ですmain()
。
プロパティが真である可能性はありますinterpol_80()
か? そうでない場合、反例は何ですか?u2 != u3
それらの間に最小距離があることを知っていれば役に立ちますか? プロパティが真であることが保証される中間計算の仮数幅を決定する方法はありますか?
編集:私が試したすべてのランダム値で、中間計算が内部的に拡張精度で行われたときに保持されたプロパティ。interpol_80()
引数を取る場合long double
、反例を構築するのは比較的簡単ですが、ここでの質問は特にdouble
引数を取る関数に関するものです。これにより、反例があったとしても、その反例を構築することがはるかに難しくなります。
注: x87 命令を生成するコンパイラは、 と に対して同じコードを生成する可能性がありますinterpol_64()
がinterpol_80()
、これは私の質問に接しています。