skip to Main Content

I am looking to round the last digit of product prices in WooCommerce with a PHP function, based on 3 rules. Price has to include cents and it does not matter if it gets rounded up or down.

If end between 0 and 4, change to 0

If end in 5, no change and stays at 5

If end between 6 and 9, change to 9

For example:

A price of $23.12 will be rounded to $23.10

A price of 39.45 will be rounded to $39.45

A price of $4.26 will be rounded to $4.29

Currently using the following code but it only rounds to a whole number.

function my_rounding_function( $price ) {
    $price = round( $price ); 
    return $price;
}

Any help would be very much appreciated! 🙂

2

Answers


  1. function my_rounding_function( $price ) {
        $price = (string) $price;
        if(strpos($price, '.'))
        {
            if($price[-1] < 5)
            {
                $price[-1] = 0;
            }
            elseif($price[-1] > 5)
            {
                $price[-1] = 9;
            }
        }
        return (float) $price;
    }
    
    echo my_rounding_function(15) . '<br>';
    echo my_rounding_function(15.3) . '<br>';
    echo my_rounding_function(15.5) . '<br>';
    echo my_rounding_function(15.8) . '<br>';
    echo my_rounding_function(15.43) . '<br>';
    echo my_rounding_function(12.45) . '<br>';
    echo my_rounding_function(12.47) . '<br>';
    
    // output
    
    // 15
    // 15
    // 15.5
    // 15.9
    // 15.4
    // 12.45
    // 12.49
    
    Login or Signup to reply.
  2. Try this. Using the BC math functions, this will guard against rounding errors. Updated to truncate (round) thousands first.

    Outputs:

    float(1)
    float(1)
    float(125.99)
    float(12.3)
    float(2.05)
    float(3.69)
    

    Code:

    <?php
    
    function roundPerceptual(float $price):float
    {
        // Truncate to precision of 2 decimals.
        $price = round($price, 2);
    
        // Get last digit using MOD 10.
        $lastDigit = bcmod($price * 100, 10);
    
        // + casts the string to a number, compare to each threshold.
        if (+$lastDigit < 5)
            $newDigit = '0';
        elseif (+$lastDigit > 5)
            $newDigit = '9';
        else
            // Equal to 5.
            $newDigit = '5';
            
        // First drop the old hundredth, then add the new hundredth.
        // Again, use + to cast to float.
        return ($price - +"0.0$lastDigit") + +"0.0$newDigit";
    }
    
    $prices = [ 1, 1.04, 125.959, 12.337, 2.05, 3.67 ];
    
    foreach ($prices as $price)
        var_dump(roundPerceptual($price));
    /*
    Outputs:
    float(1)
    float(1)
    float(125.99)
    float(12.3)
    float(2.05)
    float(3.69)
    */
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search