[PHP]round関数の使い方を徹底解説!数値の丸め処理をマスター

PHP

PHPで数値を扱う際、小数点以下を適切に丸める必要がよくあります。価格計算、統計処理、表示の整形など、様々な場面で数値の丸め処理が必要になります。この記事では、PHPのround関数について、基本的な使い方から実践的な活用方法まで詳しく解説していきます。

round関数とは?

roundは、浮動小数点数を指定した精度に丸める関数です。四捨五入が基本ですが、丸め方のモードも選択できます。

基本的な構文

float round(int|float $num, int $precision = 0, int $mode = PHP_ROUND_HALF_UP)

パラメータ:

  • $num: 丸める数値
  • $precision: 精度(小数点以下の桁数)デフォルトは0
  • $mode: 丸めモード

戻り値:

  • 丸められた浮動小数点数

丸めモード

モード説明例(1.5)
PHP_ROUND_HALF_UP0.5は切り上げ(デフォルト)2
PHP_ROUND_HALF_DOWN0.5は切り捨て1
PHP_ROUND_HALF_EVEN偶数に丸める(銀行丸め)2
PHP_ROUND_HALF_ODD奇数に丸める1

基本的な使い方

シンプルな四捨五入

<?php
// 整数に丸める(小数点以下を四捨五入)
echo round(1.4);    // 出力: 1
echo round(1.5);    // 出力: 2
echo round(1.6);    // 出力: 2
echo round(-1.5);   // 出力: -2

// 小数点第1位まで
echo round(1.234, 1);   // 出力: 1.2
echo round(1.567, 1);   // 出力: 1.6

// 小数点第2位まで
echo round(1.2345, 2);  // 出力: 1.23
echo round(1.2356, 2);  // 出力: 1.24

// 小数点第3位まで
echo round(3.14159, 3); // 出力: 3.142
?>

負の精度(整数部分を丸める)

<?php
// 10の位で丸める
echo round(1234, -1);    // 出力: 1230
echo round(1235, -1);    // 出力: 1240

// 100の位で丸める
echo round(1234, -2);    // 出力: 1200
echo round(1567, -2);    // 出力: 1600

// 1000の位で丸める
echo round(12345, -3);   // 出力: 12000
echo round(12567, -3);   // 出力: 13000
?>

丸めモードの指定

<?php
$value = 1.5;

// 0.5は切り上げ(デフォルト)
echo round($value, 0, PHP_ROUND_HALF_UP);    // 出力: 2

// 0.5は切り捨て
echo round($value, 0, PHP_ROUND_HALF_DOWN);  // 出力: 1

// 偶数に丸める(銀行丸め)
echo round(1.5, 0, PHP_ROUND_HALF_EVEN);     // 出力: 2
echo round(2.5, 0, PHP_ROUND_HALF_EVEN);     // 出力: 2

// 奇数に丸める
echo round(1.5, 0, PHP_ROUND_HALF_ODD);      // 出力: 1
echo round(2.5, 0, PHP_ROUND_HALF_ODD);      // 出力: 3
?>

ceil、floor、intvalとの違い

比較表

<?php
$value = 3.7;

echo "元の値: {$value}\n";
echo "round(): " . round($value) . "\n";      // 4 (四捨五入)
echo "ceil(): " . ceil($value) . "\n";        // 4 (切り上げ)
echo "floor(): " . floor($value) . "\n";      // 3 (切り捨て)
echo "intval(): " . intval($value) . "\n";    // 3 (整数部分のみ)

$value = 3.2;
echo "\n元の値: {$value}\n";
echo "round(): " . round($value) . "\n";      // 3 (四捨五入)
echo "ceil(): " . ceil($value) . "\n";        // 4 (切り上げ)
echo "floor(): " . floor($value) . "\n";      // 3 (切り捨て)
echo "intval(): " . intval($value) . "\n";    // 3 (整数部分のみ)

// 負の数の場合
$value = -3.7;
echo "\n元の値: {$value}\n";
echo "round(): " . round($value) . "\n";      // -4
echo "ceil(): " . ceil($value) . "\n";        // -3 (0に近い方)
echo "floor(): " . floor($value) . "\n";      // -4 (0から遠い方)
echo "intval(): " . intval($value) . "\n";    // -3
?>

実践的な使用例

1. 価格計算

<?php
/**
 * 価格計算クラス
 */
class PriceCalculator {
    
    /**
     * 消費税込み価格を計算
     */
    public static function withTax($price, $taxRate = 0.1) {
        $total = $price * (1 + $taxRate);
        return round($total);
    }
    
    /**
     * 割引価格を計算
     */
    public static function applyDiscount($price, $discountPercent) {
        $discounted = $price * (1 - $discountPercent / 100);
        return round($discounted);
    }
    
    /**
     * 単価を計算
     */
    public static function unitPrice($totalPrice, $quantity) {
        if ($quantity == 0) {
            return 0;
        }
        return round($totalPrice / $quantity, 2);
    }
    
    /**
     * 合計金額を計算(各商品を丸めてから合計)
     */
    public static function calculateTotal($items) {
        $total = 0;
        
        foreach ($items as $item) {
            $itemTotal = $item['price'] * $item['quantity'];
            $total += round($itemTotal);
        }
        
        return $total;
    }
    
    /**
     * ポイント付与額を計算
     */
    public static function calculatePoints($price, $pointRate = 0.01) {
        $points = $price * $pointRate;
        return round($points);
    }
    
    /**
     * 分割払いの月額を計算
     */
    public static function monthlyPayment($totalAmount, $months) {
        if ($months == 0) {
            return 0;
        }
        return round($totalAmount / $months);
    }
}

// 使用例
echo "=== 価格計算 ===\n";

$price = 1280;
echo "本体価格: ¥" . number_format($price) . "\n";
echo "税込価格: ¥" . number_format(PriceCalculator::withTax($price)) . "\n";

$discounted = PriceCalculator::applyDiscount($price, 15);
echo "15%OFF: ¥" . number_format($discounted) . "\n";

$unitPrice = PriceCalculator::unitPrice(5000, 3);
echo "単価(5000円÷3個): ¥" . $unitPrice . "\n";

$items = [
    ['name' => '商品A', 'price' => 1280, 'quantity' => 2],
    ['name' => '商品B', 'price' => 3500, 'quantity' => 1],
    ['name' => '商品C', 'price' => 890, 'quantity' => 3]
];

$total = PriceCalculator::calculateTotal($items);
echo "合計金額: ¥" . number_format($total) . "\n";

$points = PriceCalculator::calculatePoints($total);
echo "付与ポイント: " . number_format($points) . "pt\n";

$monthly = PriceCalculator::monthlyPayment($total, 12);
echo "月額払い(12回): ¥" . number_format($monthly) . "/月\n";
?>

2. 統計計算

<?php
/**
 * 統計計算クラス
 */
class Statistics {
    
    /**
     * 平均値を計算
     */
    public static function average($numbers, $precision = 2) {
        if (empty($numbers)) {
            return 0;
        }
        
        $avg = array_sum($numbers) / count($numbers);
        return round($avg, $precision);
    }
    
    /**
     * 標準偏差を計算
     */
    public static function standardDeviation($numbers, $precision = 2) {
        if (count($numbers) < 2) {
            return 0;
        }
        
        $avg = self::average($numbers, 10);
        $squareDiffs = array_map(function($x) use ($avg) {
            return pow($x - $avg, 2);
        }, $numbers);
        
        $variance = array_sum($squareDiffs) / count($numbers);
        $stdDev = sqrt($variance);
        
        return round($stdDev, $precision);
    }
    
    /**
     * パーセンタイルを計算
     */
    public static function percentile($numbers, $percentile, $precision = 2) {
        sort($numbers);
        $count = count($numbers);
        
        if ($count == 0) {
            return 0;
        }
        
        $index = ($percentile / 100) * ($count - 1);
        $lower = floor($index);
        $upper = ceil($index);
        
        if ($lower == $upper) {
            return round($numbers[$lower], $precision);
        }
        
        $fraction = $index - $lower;
        $value = $numbers[$lower] + $fraction * ($numbers[$upper] - $numbers[$lower]);
        
        return round($value, $precision);
    }
    
    /**
     * データサマリーを生成
     */
    public static function summarize($numbers) {
        if (empty($numbers)) {
            return null;
        }
        
        return [
            'count' => count($numbers),
            'min' => round(min($numbers), 2),
            'max' => round(max($numbers), 2),
            'mean' => self::average($numbers),
            'median' => self::percentile($numbers, 50),
            'std_dev' => self::standardDeviation($numbers),
            'q1' => self::percentile($numbers, 25),
            'q3' => self::percentile($numbers, 75)
        ];
    }
}

// 使用例
echo "\n=== 統計計算 ===\n";

$scores = [85, 92, 78, 95, 88, 76, 91, 83, 89, 94];

echo "テストスコア: " . implode(', ', $scores) . "\n\n";

$summary = Statistics::summarize($scores);

echo "統計サマリー:\n";
echo "  データ数: {$summary['count']}\n";
echo "  最小値: {$summary['min']}\n";
echo "  最大値: {$summary['max']}\n";
echo "  平均値: {$summary['mean']}\n";
echo "  中央値: {$summary['median']}\n";
echo "  標準偏差: {$summary['std_dev']}\n";
echo "  第1四分位: {$summary['q1']}\n";
echo "  第3四分位: {$summary['q3']}\n";
?>

3. 評価システム

<?php
/**
 * 評価システムクラス
 */
class RatingSystem {
    
    /**
     * 星評価を計算(0.5刻み)
     */
    public static function calculateStarRating($ratings) {
        if (empty($ratings)) {
            return 0;
        }
        
        $average = array_sum($ratings) / count($ratings);
        
        // 0.5刻みに丸める
        return round($average * 2) / 2;
    }
    
    /**
     * 星を表示
     */
    public static function renderStars($rating) {
        $fullStars = floor($rating);
        $hasHalfStar = ($rating - $fullStars) >= 0.5;
        $emptyStars = 5 - $fullStars - ($hasHalfStar ? 1 : 0);
        
        $html = str_repeat('★', $fullStars);
        if ($hasHalfStar) {
            $html .= '☆';
        }
        $html .= str_repeat('☆', $emptyStars);
        
        return $html . ' (' . $rating . ')';
    }
    
    /**
     * 評価の分布を計算
     */
    public static function ratingDistribution($ratings) {
        $distribution = array_fill(1, 5, 0);
        
        foreach ($ratings as $rating) {
            $rounded = round($rating);
            if ($rounded >= 1 && $rounded <= 5) {
                $distribution[$rounded]++;
            }
        }
        
        $total = count($ratings);
        $percentages = [];
        
        foreach ($distribution as $stars => $count) {
            $percentages[$stars] = [
                'count' => $count,
                'percentage' => $total > 0 ? round(($count / $total) * 100, 1) : 0
            ];
        }
        
        return $percentages;
    }
    
    /**
     * 総合スコアを計算(複数要素の加重平均)
     */
    public static function calculateOverallScore($scores, $weights) {
        $weightedSum = 0;
        $totalWeight = 0;
        
        foreach ($scores as $key => $score) {
            $weight = $weights[$key] ?? 1;
            $weightedSum += $score * $weight;
            $totalWeight += $weight;
        }
        
        if ($totalWeight == 0) {
            return 0;
        }
        
        return round($weightedSum / $totalWeight, 1);
    }
}

// 使用例
echo "\n=== 評価システム ===\n";

$ratings = [4.2, 4.8, 3.9, 4.5, 4.7, 4.1, 4.6, 3.8, 4.9, 4.3];

$avgRating = RatingSystem::calculateStarRating($ratings);
echo "平均評価: " . RatingSystem::renderStars($avgRating) . "\n\n";

$distribution = RatingSystem::ratingDistribution($ratings);
echo "評価の分布:\n";
for ($i = 5; $i >= 1; $i--) {
    $bar = str_repeat('■', $distribution[$i]['count']);
    echo "{$i}つ星: {$bar} {$distribution[$i]['count']}件 ({$distribution[$i]['percentage']}%)\n";
}

echo "\n=== 総合スコア ===\n";
$scores = [
    'quality' => 4.5,
    'service' => 4.2,
    'value' => 3.8,
    'location' => 4.7
];

$weights = [
    'quality' => 2,
    'service' => 2,
    'value' => 1,
    'location' => 1
];

$overall = RatingSystem::calculateOverallScore($scores, $weights);
echo "品質: {$scores['quality']} (重み: {$weights['quality']})\n";
echo "サービス: {$scores['service']} (重み: {$weights['service']})\n";
echo "価格: {$scores['value']} (重み: {$weights['value']})\n";
echo "立地: {$scores['location']} (重み: {$weights['location']})\n";
echo "総合スコア: {$overall}\n";
?>

4. パーセンテージ計算

<?php
/**
 * パーセンテージ計算クラス
 */
class PercentageCalculator {
    
    /**
     * パーセンテージを計算
     */
    public static function calculate($value, $total, $precision = 1) {
        if ($total == 0) {
            return 0;
        }
        
        $percentage = ($value / $total) * 100;
        return round($percentage, $precision);
    }
    
    /**
     * 増減率を計算
     */
    public static function changeRate($oldValue, $newValue, $precision = 1) {
        if ($oldValue == 0) {
            return $newValue > 0 ? 100 : 0;
        }
        
        $change = (($newValue - $oldValue) / $oldValue) * 100;
        return round($change, $precision);
    }
    
    /**
     * 達成率を計算
     */
    public static function achievementRate($current, $target, $precision = 1) {
        if ($target == 0) {
            return 0;
        }
        
        $rate = ($current / $target) * 100;
        return round($rate, $precision);
    }
    
    /**
     * 進捗レポートを生成
     */
    public static function progressReport($data) {
        $total = array_sum($data);
        $report = [];
        
        foreach ($data as $label => $value) {
            $percentage = self::calculate($value, $total);
            $report[$label] = [
                'value' => $value,
                'percentage' => $percentage,
                'formatted' => number_format($value) . ' (' . $percentage . '%)'
            ];
        }
        
        return $report;
    }
    
    /**
     * プログレスバーを描画
     */
    public static function renderProgressBar($percentage, $width = 50) {
        $percentage = max(0, min(100, $percentage));
        $filled = round(($percentage / 100) * $width);
        $empty = $width - $filled;
        
        $bar = '[' . str_repeat('=', $filled) . str_repeat(' ', $empty) . ']';
        return $bar . ' ' . round($percentage, 1) . '%';
    }
}

// 使用例
echo "\n=== パーセンテージ計算 ===\n";

// 得票率
$votes = ['候補A' => 1234, '候補B' => 987, '候補C' => 654];
echo "得票結果:\n";
$voteReport = PercentageCalculator::progressReport($votes);
foreach ($voteReport as $candidate => $data) {
    echo "{$candidate}: {$data['formatted']}\n";
}

// 売上増減率
echo "\n前年比:\n";
$lastYear = 1200000;
$thisYear = 1450000;
$changeRate = PercentageCalculator::changeRate($lastYear, $thisYear);
echo "昨年: ¥" . number_format($lastYear) . "\n";
echo "今年: ¥" . number_format($thisYear) . "\n";
echo "増減: " . ($changeRate >= 0 ? '+' : '') . $changeRate . "%\n";

// 目標達成率
echo "\n目標達成状況:\n";
$target = 1000000;
$current = 850000;
$achievement = PercentageCalculator::achievementRate($current, $target);
echo "目標: ¥" . number_format($target) . "\n";
echo "現在: ¥" . number_format($current) . "\n";
echo "達成率: " . PercentageCalculator::renderProgressBar($achievement) . "\n";
?>

5. 単位変換

<?php
/**
 * 単位変換クラス
 */
class UnitConverter {
    
    /**
     * バイトを人間が読みやすい形式に変換
     */
    public static function formatBytes($bytes, $precision = 2) {
        $units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
        
        $bytes = max($bytes, 0);
        $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
        $pow = min($pow, count($units) - 1);
        
        $bytes /= pow(1024, $pow);
        
        return round($bytes, $precision) . ' ' . $units[$pow];
    }
    
    /**
     * 秒を時分秒に変換
     */
    public static function formatDuration($seconds) {
        $hours = floor($seconds / 3600);
        $minutes = floor(($seconds % 3600) / 60);
        $secs = $seconds % 60;
        
        if ($hours > 0) {
            return sprintf('%d時間%d分%d秒', $hours, $minutes, round($secs));
        } elseif ($minutes > 0) {
            return sprintf('%d分%d秒', $minutes, round($secs));
        } else {
            return sprintf('%d秒', round($secs));
        }
    }
    
    /**
     * 距離を適切な単位で表示
     */
    public static function formatDistance($meters, $precision = 1) {
        if ($meters >= 1000) {
            $km = $meters / 1000;
            return round($km, $precision) . ' km';
        } else {
            return round($meters, $precision) . ' m';
        }
    }
    
    /**
     * 温度変換(摂氏⇔華氏)
     */
    public static function celsiusToFahrenheit($celsius, $precision = 1) {
        $fahrenheit = ($celsius * 9/5) + 32;
        return round($fahrenheit, $precision);
    }
    
    public static function fahrenheitToCelsius($fahrenheit, $precision = 1) {
        $celsius = ($fahrenheit - 32) * 5/9;
        return round($celsius, $precision);
    }
    
    /**
     * BMIを計算
     */
    public static function calculateBMI($weightKg, $heightCm, $precision = 1) {
        $heightM = $heightCm / 100;
        $bmi = $weightKg / ($heightM * $heightM);
        return round($bmi, $precision);
    }
}

// 使用例
echo "\n=== 単位変換 ===\n";

echo "ファイルサイズ:\n";
echo "1024 bytes = " . UnitConverter::formatBytes(1024) . "\n";
echo "1048576 bytes = " . UnitConverter::formatBytes(1048576) . "\n";
echo "1073741824 bytes = " . UnitConverter::formatBytes(1073741824) . "\n";

echo "\n時間:\n";
echo "125秒 = " . UnitConverter::formatDuration(125) . "\n";
echo "3665秒 = " . UnitConverter::formatDuration(3665) . "\n";

echo "\n距離:\n";
echo "500m = " . UnitConverter::formatDistance(500) . "\n";
echo "1500m = " . UnitConverter::formatDistance(1500) . "\n";
echo "12345m = " . UnitConverter::formatDistance(12345) . "\n";

echo "\n温度:\n";
$celsius = 25;
$fahrenheit = UnitConverter::celsiusToFahrenheit($celsius);
echo "{$celsius}°C = {$fahrenheit}°F\n";

echo "\nBMI:\n";
$weight = 70;
$height = 175;
$bmi = UnitConverter::calculateBMI($weight, $height);
echo "体重{$weight}kg、身長{$height}cm のBMI: {$bmi}\n";
?>

よくある間違いと注意点

間違い1: 浮動小数点の精度問題

<?php
// 浮動小数点の誤差
$value = 0.1 + 0.2;
echo $value;            // 0.30000000000000004
echo round($value, 1);  // 0.3

// 金額計算では注意
$price = 0.1 + 0.2;
echo round($price, 2);  // 0.3

// ✅ 金額は整数(銭単位)で計算してから変換
$cents = 10 + 20;  // 30銭
$yen = $cents / 100;  // 0.3円
?>

間違い2: 銀行丸めの誤解

<?php
// 銀行丸め(PHP_ROUND_HALF_EVEN)は偏りを減らす
$values = [1.5, 2.5, 3.5, 4.5];

echo "通常の四捨五入:\n";
foreach ($values as $v) {
    echo "$v → " . round($v, 0, PHP_ROUND_HALF_UP) . "\n";
}
// すべて切り上げ: 2, 3, 4, 5

echo "\n銀行丸め:\n";
foreach ($values as $v) {
    echo "$v → " . round($v, 0, PHP_ROUND_HALF_EVEN) . "\n";
}
// 偶数に: 2, 2, 4, 4 (偏りが少ない)
?>

間違い3: 精度の指定ミス

<?php
$value = 1234.5678;

// ❌ 精度を大きくしすぎ
$rounded = round($value, 10);  // 意味がない

// ✅ 適切な精度
$rounded = round($value, 2);   // 1234.57

// ❌ 負の精度の理解不足
$rounded = round(1234, -1);    // 1230(10の位で丸める)
?>

まとめ

round関数は、PHPで数値を丸めるための基本的な関数です。以下のポイントを押さえておきましょう。

  • 小数点以下の桁数を指定して四捨五入
  • 負の精度で整数部分も丸められる
  • 丸めモードで0.5の扱いを制御可能
  • 価格計算、統計処理、評価システムに活用
  • ceil(切り上げ)、floor(切り捨て)との使い分け
  • 浮動小数点の精度問題に注意
  • 銀行丸め(PHP_ROUND_HALF_EVEN)で偏りを軽減
  • パーセンテージや単位変換での活用

数値の丸め処理は、見た目の整形だけでなく、計算精度にも影響する重要な処理です。roundを適切に使って、正確で読みやすいデータ処理を実現しましょう!

タイトルとURLをコピーしました