5

値が浮動小数点数である連想配列がありますが、これは確率であると想定されています。そのため、それらを合計し、結果が実際には 1 であることを要求します。

$total = array_sum($array);
echo '$total = '.$total."\n";
if ($total == 1) {
    die("total is 1");
} else {
    die("total is not 1");
}

これは不思議なことに出力します:

$total = 1
total is not 1

yieldsvar_dump($total)を実行float(1)しても、$total == (float)1false が返されます。

どうしたの?

4

3 に答える 3

3

浮動小数点値は本質的に不正確であり、格納方法と丸め誤差のために互いに等しいことはほとんどありません。2 つの値が「十分に近い」かどうかを確認して、float を比較する必要があります。つまり、2 つの値の差の絶対値を、非常に小さい誤差範囲 (「イプシロン」と呼ばれることが多い) と比較します。

そのような実装の1つは次のとおりです。

if (abs($total - 1) < 0.000000001)
    die("total is 1");
} else {
    die("total is not 1");
}

アプリケーションの要件によってのみ、安全な誤差範囲とは何か、および表示のために数値を丸める必要があるポイントを正確に判断できることに注意してください。


たとえば、通貨の値を扱っていて、正確な精度が必要な場合は、浮動小数点演算を完全に放棄することをお勧めします。この場合の 1 つのオプションは、整数型を使用して数値をセントとして格納し、最後の分だけを分割してユーザーに数値を表示することです (または、分割することさえせず、代わりに文字列に小数点を挿入します)。

于 2013-09-06T17:23:29.833 に答える
2

PHP(および他の言語)の浮動小数点数は正確ではないため、(float)1実際には1.00000000000000123113または.99999999999999823477

詳細については、回答PHP - 浮動小数点数の精度を参照してください。

于 2013-09-06T17:21:22.463 に答える
1

int へのキャスト

if ((int)$total == 1)

そしてそれはうまくいくでしょう:)

編集:またはさらに良い

$total = (int)array_sum($array);
于 2013-09-06T17:23:24.407 に答える