PHP開発では、 ceil()関数は、浮動小数点数を切り上げるためによく使用されます。ただし、多くの開発者は、CEIL()を使用する場合、予期しない精度例外の問題に遭遇します。この記事では、CEIL()が異常なデータの精度を引き起こし、この問題を効果的に回避するためのいくつかの方法を導入する理由を詳細に分析します。
CEIL()は、PHPの組み込みの数学的関数であり、これはフローティングポイント数を最も近い整数まで丸めるために使用されます。例えば:
<?php
echo ceil(4.1); // 出力 5
echo ceil(9.999); // 出力 10
?>
CEIL()の機能はシンプルで明確ですが、その入力は浮動小数点数であり、浮動小数点数自体に表現精度の問題があります。
浮動小数点数はコンピューターのバイナリに保存され、多くの小数点以下は有限バイナリビットで正確に表現することはできません。たとえば、 0.1は、浮動小数点表現におけるバイナリ小数の無限のループであり、実際の保存値にわずかな偏差をもたらします。
CEIL()関数を呼び出すと、浮動小数点数の実際の保存値が予想よりわずかに小さく、またはわずかに大きい場合、 CEIL()は、予想と矛盾する結果を得る場合があります。
例えば:
<?php
$num = 1.9999999999999999;
echo ceil($num); // 予想される 2,実際、そうです 2
$num = 1.0000000000000001;
echo ceil($num); // 予想される 2,しかし、実際にはそうです 1,フローティングポイントストレージの近似は、より少ないものになるためです 1.0000000000000001
?>
現時点では、小数点の後に違いがあるようですが、実際にはフローティングポイントストレージのエラーによって引き起こされます。 CEIL()は実際の近似に従って上方に丸くなり、予期しない結果が発生する可能性があります。
<?php
$price = 19.999999999999998;
echo ceil($price); // 出力结果是 20,期待に応えます
$price2 = 19.999999999999996;
echo ceil($price2); // 出力结果是 20,期待に応えます
$price3 = 19.999999999999994;
echo ceil($price3); // 也可能出力 20,浮動小数点数のわずかなエラーにより、結果は不安定になります
?>
大量のコンピューティングまたは金融システムでは、このようなエラーはビジネスロジックエラーにつながる可能性があります。
PHPは、浮動ポイントエラーを回避するために、高精度の数学計算のためのBCMATH拡張機能を提供します。
<?php
$num = "19.999999999999998";
$result = bcadd($num, '0', 0); // 予約する0位小数,これは、下向きに丸くなることに相当します
if (bccomp($num, $result, 14) > 0) {
$result = bcadd($result, '1', 0); // もし$num結果よりも大きい,次に、上に加算します1,シミュレーションceil効果
}
echo $result; // 出力 20
?>
浮動小数点数に特定の小数の場所を丸めると、浮動小数点エラーの影響が減少する可能性があります。
<?php
$num = 19.999999999999998;
$num = round($num, 10); // 予約する10位小数
echo ceil($num);
?>
数値を文字列に変換し、ロジックをカスタマイズして、浮動小数点数の直接計算のエラーを回避します。
金融および計測システムは、すべての金額を最小ユニット(セグメントなど)に整数として保存することを推奨し、浮動小数点数を避けます。処理後、必要なユニットに戻ります。
CEIL()関数自体はエラーを発生させませんが、浮動小数点数の精度があるため、丸めの結果は期待と一致しない場合があります。
コンピューターの浮動小数点数の近似ストレージの問題が根本的な原因です。
BCMATH拡張機能を使用するか、最初に丸めを使用することにより、精度の例外を削減できます。
重要な場合には、浮動小数点数の使用を避け、高精度操作に整数または文字列を使用することをお勧めします。