7

次の場合、引き算の浮動小数点誤差によりゼロ除算は可能でしょうか?

float x, y, z;
...
if (y != 1.0)
    z = x / (y - 1.0);

言い換えれば、以下はより安全ですか?

float divisor = y - 1.0;
if (divisor != 0.0)
    z = x / divisor;
4

3 に答える 3

6

IEEE-754 浮動小数点を想定すると、それらは同等です。

有限の x と y について、x == y の場合に限り x - y == 0 であるというのは、漸進的なアンダーフローを想定した FP 算術の基本定理です。

非正規の結果が (段階的なアンダーフローではなく) ゼロにフラッシュされる場合、この定理は結果 x - y が正規の場合にのみ成立します。1.0 は適切にスケーリングされているためy - 1.0、非正規化されることはy - 1.0なく、アンダーフローの処理方法に関係なく、y が正確に 1.0 である場合にのみゼロになります。

もちろん、C++ は IEEE-754 を保証しませんが、この定理はほとんどの「妥当な」浮動小数点システムに当てはまります。

于 2012-10-10T19:04:49.433 に答える
5

これにより、正確にゼロで割ることができなくなりますが、それでも結果として終わらないというわけではありません+/-inf。分母はまだ十分に小さいため、答えは で表現できず、double最終的には になりますinf。例えば:

#include <iostream>
#include <limits>

int main(int argc, char const *argv[])
{
    double small = std::numeric_limits<double>::epsilon();
    double large = std::numeric_limits<double>::max() / small;
    std::cout << "small: " << small << std::endl;
    std::cout << "large: " << large << std::endl;
    return 0;
}

このプログラムsmallでは はゼロではありませんが、とlargeの範囲を超えるほど小さいdoubleですinf

于 2012-10-10T18:15:31.107 に答える
2

2つのコードスニペット()の間に違いはありません。実際、divisor変数をこれ以上使用しないと仮定すると、オプティマイザーは両方のフラグメントを同じバイナリコードに最適化することもできます。

ただし、浮動小数点ゼロで除算0.0しても実行時エラーは発生せず、代わりにinfまたはが生成されることに注意してください。-inf

于 2012-10-10T18:04:11.490 に答える