私は機能を持っていました:
float lerp(float alpha, float x0, float x1) {
return (1.0f - alpha) * x0 + alpha * x1;
}
見たことがない人にとってはx0 + (x1-x0)
* alpha
、後者はそれを保証しないため、これよりも望ましいlerp(1.0f, x0, x1) == x1
.
ここで、lerp
関数に追加のプロパティが必要です: I'd like lerp(alpha, x0, x1) == lerp(1-alpha, x1, x0)
. (理由については、これはより複雑な関数のおもちゃの例です。)私が思いついた、うまくいくように見える解決策は
float lerp_symmetric(float alpha, float x0, float x1) {
float w0 = 1.0f - alpha;
float w1 = 1.0f - w0;
return w0 * x0 + w1 * x1;
}
この二重減算には、0 付近と 1 付近を丸める効果がalpha = std::nextafter(0)
あり1 - alpha == 1
ます1 - (1-alpha) == 0
。私が知る限り、それは常に真実です1.0f - x == 1.0f - (1.0f - (1.0f - x))
。という効果もあるそうですw0 + w1 == 1.0f
。
質問:
- これは合理的なアプローチですか?
- 自分のコンパイラが自分のやりたいことをやってくれると信頼できますか? 特に、Windows では、部分的な結果に対してより高い精度を使用することがあることを知っています。また、コンパイラが代数を実行できることも知っています。代数的に明らかに 1-(1-x)==x です。
これは、Clang、VisualStudio、および gcc を使用した C++11 です。