PHP Rounding Numbers

后端 未结 6 1484
不思量自难忘°
不思量自难忘° 2020-12-21 07:47

I cannot seem to figure out how to always round up in PHP. ceil() would be the obvious choice but I need the same functionality that round() provid

相关标签:
6条回答
  • 2020-12-21 08:23

    Some of these answers have issues with floating point arithmetic which can fail as shown in this answer. For a bulletproof solution in all cases, use these:

    /**
     * Used to round up based on the decimal place, for example rounding up to the nearest penny
     * http://stackoverflow.com/questions/8239600/rounding-up-to-the-second-decimal-place
     * @param float $value
     * @param integer $precision
     * @return number
     */
    public function Ceiling($value, $precision = 0) {
        $offset = 0.5;
        if ($precision !== 0)
            $offset /= pow(10, $precision);
        $final = round($value + $offset, $precision, PHP_ROUND_HALF_DOWN);
        return ($final == -0 ? 0 : $final);
    }
    
    /**
     * Used to round up based on the decimal place, for example rounding up to the nearest penny
     * http://stackoverflow.com/questions/8239600/rounding-up-to-the-second-decimal-place
     * @param float $value
     * @param integer $precision
     * @return number
     */
    public function Floor($value, $precision = 0) {
        $offset = -0.5;
        if ($precision !== 0)
            $offset /= pow(10, $precision);
        $final = round($value + $offset, $precision, PHP_ROUND_HALF_UP);
        return ($final == -0 ? 0 : $final);
    }
    
    0 讨论(0)
  • 2020-12-21 08:28

    As version ceil(pow(10, $precision) * $value) / pow(10, $precision); fails in some cases, e.g. round_up(2.22, 2) gives incorrect 2.23 as mentioned here, so I have adapted this string solution for round_down() to our round_up() problem. This is the result (a negative precision is not covered):

    function round_up($value, $precision) {        
        $value = (float)$value;
        $precision = (int)$precision;
        if ($precision < 0) { 
            $precision = 0;
        }
        $decPointPosition = strpos($value, '.');
        if ($decPointPosition === false) { 
            return $value;
        }
        $floorValue = (float)substr($value, 0, $decPointPosition + $precision + 1);
        $followingDecimals = (int)substr($value, $decPointPosition + $precision + 1);
        if ($followingDecimals) {
            $ceilValue = $floorValue + pow(10, -$precision); // does this give always right result?
        }
        else {
            $ceilValue = $floorValue;
        }
        return $ceilValue;                
    }
    

    I don't know it is bulletproof, but at least it removes the above mentioned fail. I have done no binary-to-decimal-math-analysis but if $floorValue + pow(10, 0 - $precision) works always as expected then it should be ok. If you will find some failing case let me know - we should look for another solution :)

    0 讨论(0)
  • 2020-12-21 08:36

    From a comment on http://php.net/manual/en/function.ceil.php:

    Quick and dirty `ceil` type function with precision capability.
    
    function ceiling($value, $precision = 0) {
        return ceil($value * pow(10, $precision)) / pow(10, $precision);
    }
    
    0 讨论(0)
  • 2020-12-21 08:38

    You could divide by 10, ceil(); and then multiply by ten

    0 讨论(0)
  • 2020-12-21 08:42
    echo 10*ceil($number/10);
    
    0 讨论(0)
  • 2020-12-21 08:45

    One more solution for ceil with precision, no pow, it looks like works 9 digits both sides:

    $v = 123400100100100101;
    $a1 = 444444444.4;
    $a2 = .04444444444;
    $b1 = 111111111.1;
    $b2 = .01111111111;
    echo $v . "\n";
    for ($i = 0; $i < 18; $i ++) {
        $v = $v/10;
        for ($j = -9; $j < 10; $j++) {
            echo $i . ':' . $j . ":" . round($v
                + round($a1, $j + 1) + round($a2, $j + 1)
                - round($a1, $j) - round($a2, $j)
                + round($b1, $j + 1) + round($b2, $j + 1)
                - round($b1, $j) - round ($b2, $j),
                $j, PHP_ROUND_HALF_DOWN) . "\n";
        }
    }
    
    0 讨论(0)
提交回复
热议问题