四捨五入と偶数丸め (PHP8.4以降)

PHP8.4で、round()関数に丸め方のオプションが追加されました。

端数がちょうど5だった場合の処理が選べるようになります。オプションは

  • RoundingMode::HalfAwayFromZero : 0から離れる方向へ丸める
  • RoundingMode::HalfTowardsZero : 0に近づく方向へ丸める
  • RoundingMode::HalfEven : 偶数側に丸める
  • RoundingMode::HalfOdd : 奇数側に丸める

です。未指定だった場合の処理はRoundingMode::HalfAwayFromZeroです。

偶数丸め(銀行丸め)

単純な四捨五入だと、端数5を切り上げるため、データ全体としては正の方向へわずかにずれます。一方で、偶数丸めだと、端数5は切り上げる場合と切り捨てる場合があり、データ全体の誤差は抑えられます。偶数丸めは銀行丸めとも呼ぶらしいです。

実際に実行してみた

以下のようなコードを実行してみました。

    // creates a sample $data 1 - 99
    $data = [];
    for($i = 1; $i < 100; $i++){
        $data[] = $i ;
    }

    $resultRaw = 0;
    $resultHalfAwayFromZero = 0;
    $resultHalfEven = 0;

    // pickups randomly from $data
    $times = 10000;
    for($i = 0; $i < $times; $i++){
        shuffle($data);
        $resultRaw += $data[0];
        $resultHalfAwayFromZero += round($data[0],-1, RoundingMode::HalfAwayFromZero);
        $resultHalfEven += round($data[0],-1, RoundingMode::HalfEven);
    }

    echo '元データ: ' . $resultRaw . '<br>' . PHP_EOL;
    echo '四捨五入: ' . $resultHalfAwayFromZero . '<br>' . PHP_EOL;
    echo '偶数丸め: ' . $resultHalfEven . '<br>' . PHP_EOL;

実行結果は↓ のようになりました。

    元データ: 499984
    四捨五入: 504890
    偶数丸め: 499910

偶数丸めのほうが、元データとの差が少なかったです。

既存システムの変更は必要か?

偶数丸めのほうが誤差が少ないようです。とはいえ、では偶数丸めを採用すればよいか、というと、新規プロダクトなら採用すればよいでしょう。一方で既存システムでは偶数丸めに変更する必要性は低いと思われます。

既存システムが四捨五入だった場合には、もちろん誤算の観点からいえばより良くなります。しかし、いままで四捨五入が受け入れられていたのであれば、四捨五入による誤差も許容されていたわけです。あえて変更しなくても良さそうに思います。

新着ブログ記事
ウェブ集客

クイズ、計算式など、ホームページ訪問者の興味・関心・満足度を高めるコンテンツを提供する仕組み。一度来てくださった方の再訪問率を高める。

濃い見込み客を見つけるホームページ自動見積もりシステム

自動見積計算と見積PDF作成を行うサービスです。濃い見込み客を抽出する仕組みで、御社のホームページを営業マンにします。

否定で終わらないウェブメディア

弊社運営のウェブメディアでは、否定レビューで終わらない仕組みを導入しています。