PHP
downloads | documentation | faq | getting help | mailing lists | licenses | wiki | reporting bugs | php.net sites | links | conferences | my php.net

search for in the

sin> <rand
Last updated: Sun, 25 Nov 2007

view this page in

round

(PHP 4, PHP 5)

round — 对浮点数进行四舍五入

说明

float round ( float $val [, int $precision ] )

返回将 val 根据指定精度 precision (十进制小数点后数字的数目)进行四舍五入的结果。precision 也可以是负数或零(默认值)。

Example#1 round() 例子

<?php
echo round(3.4);         // 3
echo round(3.5);         // 4
echo round(3.6);         // 4
echo round(3.60);      // 4
echo round(1.955832);  // 1.96
echo round(1241757, -3); // 1242000
echo round(5.0452);    // 5.05
echo round(5.0552);    // 5.06
?>

Note: PHP 默认不能正确处理类似 "12,300.2" 的字符串。见字符串转换为数值

Note: precision 参数是在 PHP 4 中被引入的。

参见 ceil()floor()number_format()



sin> <rand
Last updated: Sun, 25 Nov 2007
 
add a note add a note User Contributed Notes
round
domenicospina(A.T.)hotmail.com
08-Jan-2009 06:45
Many people write and say wrong. If round function do something wrong, user custom function that try to solve bugs,  using integrate round function, are even more wrong!!! Only way to solve this issue if you want round float numbers to any precision, is casting number as string and working with strings, using "UMAN" algorithm!!!

If you want, try my simply soluction that work with any precision (i'm using it in my erp soft)

<?php

function arrotonda($number,$approx=0)
{
   
$number = sprintf("%s",sprintf("%f",$number));
   
$parts = explode(".",$number);
   
$integers = $parts[0];
   
$decimals = $parts[1];
   
    if (
strpos($integers,"-")!==false){
       
$integers = str_replace("-","",$integers);
       
$negative = true;
    }
   
    if(
$approx<1)
    {
        if (
$decimals{0}>=5)
           
$integers++;       
        return
$integers;
    }
   
    else{
   
       
$float = explode(".",($decimals/pow(10,strlen($decimals)))*pow(10,$approx));
       
$my_decimals = $float[0];
        if(
$decimals{$approx}>=5)
           
$my_decimals++;
       
       
$total_decimals = ($my_decimals/pow(10,$approx));
    }

   
$my_number     =      sprintf("%s",sprintf("%f",($integers+$total_decimals)));
   
$padding    =     (strpos($my_number,".")+1)+$approx;
   
$my_number    =     str_pad($my_number,$padding,"0");
   
$my_number    =    substr($my_number,0,strpos($my_number,".")+$approx+1);
   
$my_number     =     $negative?("-".$my_number):$my_number;
   
    return
$my_number;   
}

?>
Anonymous
24-Dec-2008 09:31
Precision rounding.  Works for any value, including negative values, and values between 1 and 0.

<?php
function roundPrecision($value, $precision=3 ){
   
$round = $precision - floor(log10(abs($value))) - 1;
    return
round($value, $round);
}
?>
Montoya
31-Oct-2008 06:36
Here's a quick gotcha:

I was fetching some data from a web service using cURL & SimpleXML and getting values like 28.75. I was then rounding these values but getting 28 instead of 29.

Turns out the values were strings, so round() would treat them as integers, and casting to an int drops off the decimals (like floor()).

So I had to do:

round( (double) $val );

HTH!
darkstream777 at gmx dot net
13-Oct-2008 11:16
Here is another method to round digits with precision support:

<?php
function roundDigits( $value, $precision=0 )
{
   
$precisionFactor = ($precision == 0) ? 1 : pow( 10, $precision );
    return
round( $value * $precisionFactor ) / $precisionFactor;
}
?>


Example:
echo roundDigits(1.859438,2) . "<br />"; // equals 1.86
echo roundDigits(1.444444,4); // equals 1.4444

Greetings, darki
Chris
01-Sep-2008 08:05
I dont think it is a bug as such but when rounding genrally you tend to only round from the digit after the precision you want.

The only way to get arround this is by rounding it twice with diffrent precisions:

<?php
$round1
= round(8.1246, 3); //8.125
$round2 = round($round1, 2); //8.13
echo $round2;
?>
Chris
21-Aug-2008 12:06
Ito only rounds the (33615 / 33333) )*100 the -100 doesn't get rounded
try this:

<?php
round
( (((33615 / 33333) )*100 -100) , 2)
?>
chris at chrisstockton dot org
31-Jul-2008 07:05
In case anyone has a problem like me ever, were you are doing very large stat calculations on a array and end up with floats with way to large of precision. A good way to round them all to N length is below.

<?php
    public
function recursiveRound(array &$arr, $precision)
    {
        foreach(
$arr as $key => $val) {
            if(
is_array($val)) {
               
$this->recursiveRound($arr[$key], $precision);
            } elseif(
is_float($val)) {
               
$arr[$key] = round($arr[$key], $precision);
            }
        }
        return
$arr;
    }
?>
Darryl Kuhn
30-Jul-2008 07:59
I needed a round up function with precision which surprisingly did not exist (at least that I could see). This does the trick:

<?php
function roundUp( $value, $precision=0 )
{
   
// If the precision is 0 then default the factor to 1, otherwise
    // use 10^$precision. This effectively shifts the decimal point to the
    // right.
   
if ( $precision == 0 ) {
       
$precisionFactor = 1;
    }
    else {
       
$precisionFactor = pow( 10, $precision );
    }

   
// ceil doesn't have any notion of precision, so by multiplying by
    // the right factor and then dividing by the same factor we
    // emulate a precision
   
return ceil( $value * $precisionFactor )/$precisionFactor;
}
?>
Jeremy
10-Jul-2008 09:10
Ahh. Found another bug in my bankers_round function. This time it comes when the string is too short (ie 1 character).

To adjust this, instead of type casting $x, I am using number_format and giving it an arbitrary precision of 13 digits. (Why 13? Why not!)

Old
<?php $p = $precision + 1; $x_str = (string)$x; ?>

New
<?php $p = $precision + 1; $x_str = number_format($x, 13, '.', ''); ?>

Jeremy
Jeremy (aka Mr. Pet Gerbil)
09-Jul-2008 05:09
My function I wrote back in ... 2006 ... has a bug or two in it. First off, I didn't have a precision factor, something I found to require later on. Second, it didn't return proper values for rounding when there are digits following the digit after the precision digit (now that's a long winded sentence). I've tested it with as many possible variables as I can think of. Time to give it to you guys to really destroy.

Jeremy

<?php
function bankers_round ($x, $precision = 2) {
   
$p = $precision + 1; $x_str = (string)$x;                       # Set precision identifier and convert input to a string (for substrings)
   
$x_t_pos = strpos($x_str, '.') + $p; $x_h_pos = $x_t_pos - 1;   # Get positions of digits we're interested in
    /* Now this is the real math
     * If the digit after the precision digit is a 5:
     *      if the precision digit is even, round up
     *      if the precision digit is odd, and there are no digits following the digit after the precision digit, round down
     *      if the precision digit is odd, and there are digits following the digit after the precision digit, round up
     */
   
if ($x_str[$x_t_pos] == 5) $x_str[$x_t_pos] = ((int)$x_str[$x_h_pos] & 1) ? 9 : ($x-round($x_str, $p) > 0) ? 9 : 0;
    return (float)
round ($x_str, $precision);
}
?>
richard at happymango dot me dot uk
10-Jun-2008 07:13
In complement to the my last post, roundTime(), here are two other functions. ceilTime() and floorTime() which round up or down to the specified increment respectively.
 
<?php
//RSS: 10/06/08 rounds a timestamp to the next specified increment
//only works for increments less than or equal to 1 hour
//EG: ceilTime("15 Minutes"); rounds the time right now to the next 15 minutes 11:12 rounds to 11:15
function ceilTime($increment, $timestamp=0)
{
    if(!
$timestamp) $timestamp = time();
   
   
$increment = strtotime($increment, 1) - 1;
   
$this_hour = strtotime(date("Y-m-d H:", strtotime("-1 Hour", $timestamp))."00:00");
   
$next_hour = strtotime(date("Y-m-d H:", strtotime("+1 Hour", $timestamp))."00:00");

   
$increments = array();
   
$differences = array();
   
    for(
$i = $this_hour; $i <= $next_hour; $i += $increment)
    {
        if(
$i > $timestamp) return $i;
    }
}

//RSS: 10/06/08 rounds a timestamp to the last specified increment
//only works for increments less than or equal to 1 hour
//EG: floorTime("15 Minutes"); rounds the time right now to the last 15 minutes 11:12 rounds to 11:00
function floorTime($increment, $timestamp=0)
{
    if(!
$timestamp) $timestamp = time();
   
   
$increment = strtotime($increment, 1) - 1;
   
$this_hour = strtotime(date("Y-m-d H:", strtotime("-1 Hour", $timestamp))."00:00");
   
$next_hour = strtotime(date("Y-m-d H:", strtotime("+1 Hour", $timestamp))."00:00");

   
$increments = array();
   
$differences = array();
   
    for(
$i = $next_hour; $i >= $this_hour; $i -= $increment)
    {
        if(
$i < $timestamp) return $i;
    }
}

?>
richard at happymango dot me dot uk
10-Jun-2008 06:41
If you want to round a timestamp to the closest specified increment, for example to the closest 15 minutes, then this function could help

Definition:
int roundTime ( string $increment[, int $timestamp] )

Parameters:
$increment is a string like you would for strtotime (but dont add a + or - to the front)
$timestamp (optional) the timestamp used to calculate the returned value.

Return Value:
returns timestamp

this function only works for increments less than or equal to an hour

Its not pretty but it works.

<?php

function roundTime($increment, $timestamp=0)
{
    if(!
$timestamp) $timestamp = time();
   
   
$increment = strtotime($increment, 1) - 1;
   
$this_hour = strtotime(date("Y-m-d H:", strtotime("-1 Hour", $timestamp))."00:00");
   
$next_hour = strtotime(date("Y-m-d H:", strtotime("+1 Hour", $timestamp))."00:00");

   
$increments = array();
   
$differences = array();
   
    for(
$i = $this_hour; $i <= $next_hour; $i += $increment)
    {
       
$increments []= $i;
       
$differences []= ($timestamp > $i)? $timestamp - $i : $i - $timestamp;
    }
   
   
arsort($differences);
   
   
$key = array_pop(array_keys($differences));
   
    return
$increments[$key];
}

////////////
//EXAMPLE //
////////////

$result = roundtime("15 minutes");

echo
date("H:i", time())." rounded to closest $increment is ".date("H:i", $result);

//11:24 rounded to closest 15 minutes is 11:30
?>
Alix Axel
28-May-2008 11:20
If you are looking (like I was) for a function to round to the nearest last ending digit(s) please visit http://www.alixaxel.com/wordpress/wp-content/2008/05/Round.php for the code.
tovkjoo at yahoo dot com
21-May-2008 10:48
Round nearest number
function roundnum($num, $nearest){
    return round($num / $nearest) * $nearest;
}
Anonymous
24-Apr-2008 04:00
If you want 5799.99 to round to 5800.00, then:

$discount = '5799.995';
$discount = round($discount, -2);

See e.g.: echo round(1241757, -3); // 1242000
Anonymous
24-Apr-2008 01:47
$discount = '5799.995';
$discount = round($discount, 2);

// rounds to 5799.99, but should be 5800.00
php rookie
22-Apr-2008 07:09
Someone stated that round() does wrong rounding, e.g.

round(3.145) -> 3.14 instead of expected 3.15

But there's a special case if the last digit is a '5', if you want to have statistical correct values after rounding. The english term for that needed method is called 'round to even', which means to round to the nearest even number.

For example:
3.145 -> 3.1_4_ because in 3.1_5_  the 5 is not even
3.155 -> 3.1_6_ because 3.1_5_ still is not even :-)

The reason for this is explained quite simply:
Assume to have the following values
0.1, 0.2, 0.3, ... 1.7, 1.8, 1.9

The mean (or average) of this group is 1.

But what happens if you round this numbers before calculating the mean value?

0.1 to 0.4 are round down to zero, 0.6 to 0.9 are round up to 1.
1.1 to 1.4 -> 1, 1.6 to 1.9 -> 2.
Up to here the mean value is 1 (which is correct of course).

If both 0.5 and 1.5 are round up also the mean value would change (to something like 1.05....). So the solution is to round 0.5 down to 0, and 1.5 up to 2 ... -> mean value is exactly 1 !
alveda at pinoywebsys dot com
20-Apr-2008 03:09
My simple work around.

function my_round($value, $precision=0) {
    return round(round($value*pow(10, $precision+1), 0), -1)/pow(10, $precision+1);
}
ThOmAs
16-Apr-2008 07:32
Excample :
<?php
function if_this_an_int($arg)
{
if(
strlen($arg) > 0 && is_numeric($arg) && $arg > 0)
{
echo
round($arg);
}
}
$test = 1.3;
echo
if_this_an_int($test);
?>

You can use this function for any formular in your website, when you must to check if not empty or zero and it's a number

I hope you can need this.
kjohnson at zootweb dot com
11-Apr-2008 05:12
Examples:

echo round(1100000); // 1100000
echo round(1200000); // 1.2E+6
echo round(1300000); // 1300000
echo round(1400000); // 1.4E+6
admin at studio-gepard dot pl
30-Mar-2008 05:08
Here is basic function I sue to round file size. It gives as output text, so it's very easy to use it in your applications.

$SIZE is file size in MB.
function output is text.

<?php
function sizetotext($SIZE){
 
  if (
$SIZE>=1024){
    
$SIZE=round($SIZE/1024,2);
     return
$SIZE."GB";
  }else{
    if (
$SIZE>=1){
      return
$SIZE."MB";
    }else{
     
$SIZE=$SIZE*1000;
      return
"~".$SIZE."KB";
    }
  }

}
?>
timpleasenospamshaw at mailnospam dot usa dot com
15-Mar-2008 01:38
After reading all of the notes for this page, I suggest that any casual PHP coder beware. Please consult someone with an actual understanding of floating point issues before developing a serious application, such as one dealing with money in any form.

Also, in the note I just posted, I suggested using integers for monetary values. PHP does not currently support 64 bit integers on platforms where int is normally 32 bits, so watch out for overflow occuring near $2 million or $20 million, depending on whether the integers represent mils or cents. I believe it may be possible for PHP to give an incorrect result without an error condition for some integer overflow conditions.

Again, please see
http://www.php.net/float
timnotforspamshaw at mailNOSPAM dot usa dot com
15-Mar-2008 01:02
Many people posting notes here are confused.

Do not assume that what you see for a floating point number is the actual value. The value 0.1 can not be represented exactly in binary floating point, no matter how many bits are present in the floating point representation, because 5 does not go into any power of 2. Most other fractions can also not be represented exactly either.

For instance,

<?php
echo 0.285 + 0.0          - 0.285
printf
("%.17f", 0.285)    - 0.28499999999999998
?>

There is no problem with round(0.285) rounding in the incorrect direction; it is rounding in the correct direction for the argument it is receiving. The problem is that the coder is not being careful with tiny floating point errors that can creep in and become large when things are rounded.

For money, one solution is to always store things as an integer, e.g. in cents or mils (thousandths of a monetary unit). Then there is no floating point rounding problem.

For other values, where floating point is necessary, I usually add a very small epsilon before rounding, usually about 1e-6 less than the rounding digit. This causes things that look like they should be rounded up, to actually round up.

Also, remember to never simply compare a floating point number against another number, even zero, and expect the comparison to work as expected, because of these tiny errors. Always use a small epsilon in the comparison. The direction of the epsilon depends on the intent of the comparison: $a > $b becomes $a > $b + $epsilon, $a >= $b becomes $a >= $b - $epsilon, and $a == $b becomes ($a <= $b + $epsilon && $a >= $b - $epsilon).

Please see
www.php.net/float
domenicospina at hotmail dot com
29-Feb-2008 06:36
Hi,  approximations with Function Round() are WRONG!!
If you tray to round 2.135 to second digit, expexted value is "2.14", but returned value is "2.13" : WRONG!!!

I'm developing a managerial program(php-based) and i must solve this bug (currently in php5.2.5) with my function:

function toFixed($number,$approx=0,$visualizza='E',$format='default')
{
    $number = sprintf("%s",sprintf("%f",$number));
    $parts = explode(".",$number);
    $integers = $parts[0];
    $decimals = $parts[1];
   
    if (strpos($integers,"-")!==false){
        $integers = str_replace("-","",$integers);
        $negative = true;
    }
   
    if($approx<1)
    {
        if ($decimals{0}>=5)
        {
            $integers++;
        }
       
        return $integers;
    }
   
    else{
   
        $float = explode(".",($decimals/pow(10,strlen($decimals)))*pow(10,$approx));
        $my_decimals = $float[0];
        if($decimals{$approx}>=5)
        {
            $my_decimals++;
        }   
       
        $total_decimals = ($my_decimals/pow(10,$approx));
    }

    $my_number     =      sprintf("%s",sprintf("%f",($integers+$total_decimals)));
    $my_number     =     (strpos($my_number,".")===false)?($my_number."."):$my_number;
    $padding    =     (strpos($my_number,".")+1)+$approx;
    $my_number    =     str_pad($my_number,$padding,"0");
    $my_number    =    substr($my_number,0,strpos($my_number,".")+$approx+1);
    $my_number     =     $negative?("-".$my_number):$my_number;
   
    switch($visualizza)
    {
        case 'E': //editing
            return $my_number;
        break;
       
        case 'V': //video
            return formatNumber($my_number,$approx,$format);
        break;
    }
   
   
}
felix dot ospald at gmx dot de
28-Feb-2008 08:19
BEWARE!:
round(0.1)
round(-0.1)
gives "0" and "-0"
so
echo (((round(0.1).'EUR') == (round(-0.1).'EUR')) ? 'OK' : 'BUG OR FEATURE?');
gives: "BUG OR FEATURE?"
number_format shows the same behaviour
skinnepa at hotmail dot com
28-Feb-2008 05:16
Remember kids that rounding a DB NULL will result in a 0 zero;  test your NULLs!
altsoph
08-Feb-2008 02:30
Another way to code all 7 rounding methods according IEEE754 standart:

<?php
// We need precision parameter for ceil & floor
function p_ceil( $val, $d )
{
    return
ceil($val * pow (10, $d) )/ pow (10, $d) ;
}
function
p_floor( $val, $d )
{
    return
floor($val * pow (10, $d) )/ pow (10, $d) ;
}

// We need signum
function sgn($x)
{
    return
$x ? ($x>0 ? 1 : -1) : 0;
}

// Now seven functions for standart rounding methods
function round_down($num, $d = 0)
{
    return
sgn($num)*p_floor(abs($num), $d);
}
function
round_up($num, $d = 0)
{
    return
sgn($num)*p_ceil(abs($num), $d);
}
function
round_half_even($num, $d = 0)
{
    if(
round($num,$d) == round_half_down($num,$d) )
        return
round($num,$d);

   
$pre_digit = round_down( $num, $d );

    if( (
$pre_digit/2) == round_down($pre_digit/2,$d) )
        return
round_down($num, $d);
    else
        return
round_up($num, $d);
}
function
round_ceiling($num, $d = 0)
{
    return
p_ceil($num, $d);
}
function
round_floor($num, $d = 0)
{
    return
p_floor($num, $d);
}
function
round_half_down($num, $d = 0)
{
    return ((
2*round_up($num,$d)==round_up(2*$num,$d))
        ?
round($num,$d)                     : round_down($num,$d) );   
}
function
round_half_up($num, $d = 0)
{
    return
round($num, $d);
}

?>

My article (in Russian) about rounding in PHP is here:
http://altsoph.ru/?p=521
denis at softmaster dot com dot ua
31-Jan-2008 04:08
There is a bug like round up (100*1.1);
In PHP round_up(100*1.1) you got 110.01;
A true value is 100*1.1 = 110;
A elegant decision of this problem (money round up) is:

<?
// Money round up
function mround($value) {
  return
ceil((string)($value*100))/100;
}
?>

(string)($value*100) - this is decision! =)
martinr at maarja dot net
13-Jan-2008 07:40
Please note that the format of this functions output also depends on your locale settings. For example, if you have set your locale to some country that uses commas to separate decimal places, the output of this function also uses commas instead of dots.

This might be a problem when you are feeding the rounded float number into a database, which requires you to separate decimal places with dots.

See it in action:
<?php
   
echo round('3.5558', 2);
   
setlocale(constant('LC_ALL'), 'et_EE.UTF-8');
    echo
'<br />'. round('3.5558', 2);
?>

The output will be:
3.56
3,56
xellisx at gmail dot com
14-Nov-2007 07:58
[quote]
This can be much more efficient:
<?php
function roundup ($value, $dp)
{
    return
ceil($value*pow(10, $dp))/pow(10, $dp);
}

function
rounddown ($value, $dp)
{
    return
floor($value*pow(10, $dp))/pow(10, $dp);
}
?>

Much cleaner, isn't it ;)?
[/quote]

Unfortunately - it wasn't formatting the number right and you have to figure out which way you want to go.

Using the code - I've come up with this:
<php
function fract_round($n, $dp)
 {
  if(round($n, $dp) > $n)
   {
    return number_format(ceil($n*pow(10, $dp))/pow(10,$dp),$dp);
   }
  else
   {
    return number_format(floor($n*pow(10,$dp))/pow(10,$dp),$dp);
   }
 }
?>

Of course we could just do this:
<?php
function fract_round($n, $dp)
 {
   return
number_format(round($n, $dp), $dp);
 }
?>
mark at customcartons dot com dot au
10-Nov-2007 01:39
[quot]
This can be much more efficient:
<?php
function roundup ($value, $dp)
{
    return
ceil($value*pow(10, $dp))/pow(10, $dp);
}

function
rounddown ($value, $dp)
{
    return
floor($value*pow(10, $dp))/pow(10, $dp);
}
?>

Much cleaner, isn't it ;)?
[/quot]

Nice cleanup job, you've also managed to solve the issue which "xploded at lycos.com" noted earlier about passing 0 as the value. Thanks to you both for your input :-)
trhodes at plus dot net
07-Nov-2007 01:48
smithaapc's trueRound() function is also broken. For example:

trueRound(1.11, 3) //returns 1.1, should return 1.11

Here's a function that uses PHP's round() to calculate significant figures:

<?php
function sigFig($value, $sigFigs) {
   
$exponent = floor(log10($value) + 1);
   
$significand = $value / pow(10, $exponent);
   
$significand = round($significand * pow(10, $sigFigs)) / pow(10, $sigFigs);
   
$value = $significand * pow(10, $exponent);
    return(
$value);
}

//Examples
sigFig(123.45, 6); // 123.45 (doesn't pad with zeros)
sigFig(123.45, 5); // 123.45
sigFig(123.45, 4); // 123.5
sigFig(123.45, 3); // 123
sigFig(123.45, 2); // 120 (rounds to 2 figures)
sigFig(123.45, 1); // 100
sigFig(123.45, 0); // 0 (!)
?>
KingIsulgard
29-Oct-2007 09:23
[quote]I'm sure its been done before, but here's my example of a round up function.

This function allows you to specify the number of decimal places to round up to.

Eg, when rounding up to 3 decimal places, this function adds 0.0005 to the original value and performs round(), or for 6 decimal places, adds 0.0000005 and performs round(), etc...

Hopefully some of you will find it useful:

<?php
function roundup ($value, $dp)
{
   
// Offset to add to $value to cause round() to round up to nearest significant digit for '$dp' decimal places
   
$offset = pow (10, -($dp + 1)) * 5;
    return
round ($value + $offset, $dp);
}
?>

Please post if you have any comments or improvements on this :-) [/quote]

This can be much more efficient:
<?php
function roundup ($value, $dp)
{
    return
ceil($value*pow(10, $dp))/pow(10, $dp);
}

function
rounddown ($value, $dp)
{
    return
floor($value*pow(10, $dp))/pow(10, $dp);
}
?>

Much cleaner, isn't it ;)?
thawee from thailand
11-Oct-2007 12:41
my round function
function rounding($n,$d){
    $base=intval($n);
    $n=number_format($n,25);
    $dotpos=strpos($n,".");
    $strlen=strlen($n);
    $b= substr($n,$dotpos+1,$strlen-$dotpos);
    $j=1;
    $p=0;
    for($i=strlen($b);$i>$d;$i--){
                $c=substr($b,-$j,1)+$p;
        if($c<5){
            $p=0;
        }else{
            $p=1;
        }
        $j++;
    }
 return $base+((substr($b,0,$d)+$p)/pow(10,$d));
}
xploded at lycos.com
05-Sep-2007 12:31
to mark at customcartons dot com dot au

found your roundup very useful, the only problem is if the value passed is 0.00 as it roundsup to 0.01 which may not be desired.

I modified the return statement to:

return ($value>0) ? round($value+$offset,$dp) : '0.00';

regards
James
Secret at secret dot com
24-Aug-2007 01:26
Round down..

A very simple way to round down is the following..

$numbera=41;
$numberb=3;

$sum=$numbera/$numberb;

echo $sum;   // Will give 13.66666.....

$rounddownsum=(int)($numbera/$numberb);

echo $rounddownsum;   // Will give 13    ;o)

If you wana round decimals simply multiply the variables with 10...100...1000 or whatever before performing this action.. Then divide back after calculations.. then ex.

$numbera=41;
$numberb=3;

$sum=$numbera/$numberb;

$sum=(int)($sum*1000);

$sum=$sum/1000;

echo $sum;   // Will give 13.666

Hope that helps someone... ;o)
mark at customcartons dot com dot au
06-Aug-2007 09:39
I'm sure its been done before, but here's my example of a round up function.

This function allows you to specify the number of decimal places to round up to.

Eg, when rounding up to 3 decimal places, this function adds 0.0005 to the original value and performs round(), or for 6 decimal places, adds 0.0000005 and performs round(), etc...

Hopefully some of you will find it useful:

<?php
function roundup ($value, $dp)
{
   
// Offset to add to $value to cause round() to round up to nearest significant digit for '$dp' decimal places
   
$offset = pow (10, -($dp + 1)) * 5;
    return
round ($value + $offset, $dp);
}
?>

Please post if you have any comments or improvements on this :-)
Pascal Hofmann
05-Aug-2007 02:21
The function from Felix Schwarz returns wrong results for values near 0. bccomp should be called with param $scale.

function bcround ($number, $decimals, $precision) {
    $precision_add = str_repeat("5",$precision);
    if (bccomp($number,0, $decimals+$precision) > 0) {
        return (bcadd (bcadd ($number, "0.".str_repeat("0",$decimals).$precision_add, $decimals+$precision), 0, $decimals));
    }
    else {
        return (bcadd (bcsub ($number, "0.".str_repeat("0",$decimals).$precision_add, $decimals+$precision), 0, $decimals));
    }
}
smithaapc at NOSPAM dot yahoo dot com
27-Jul-2007 06:44
round() is broken, plain and simple. The solution must take into account all of the digits of a given number during rounding. Truncating the number before the rounding eliminates valuable information. Consider:
  myRound(12.4444444443, 2) = 12.45 ... not quite.

Try this out instead:
  function trueRound($value, $figs=1) {
    if(is_numeric($value) && is_int($figs) && $figs > 0) {
// must adjust $figs down 1 for computing significant figures
      $figs--;
// $prec ensures all of the original digits are included in the sprintf format
      $prec = strpos($value, '.') === false ? strlen($value)-1 : strlen($value)-2;
      $sci = sprintf('%.'.$prec.'e', $value);
      list($sig, $mant) = explode('e', $sci);
// $base includes all of the significant digits, $test contains all the remaining digits
      list($base, $test) = explode('.', $sig * pow(10, $figs));
// All 4's on the left side of $test will not be significant in the rounding
      $test = preg_replace('/^4+/', '', $test);
// The first digit in $test that is not a 4 will determine the direction of the rounding
      $test = preg_replace('/^(\d)\d+/', '$1', $test);
      if($test > 4) {
// If the digit is > 4, then simply round up by adding 1 ...
        $base += 1;
      }
// ... then simply adjust the decimal point
      $value = $base * pow(10, $mant-$figs);
    }
      return($value);
  }

Note this function rounds up to a number of significant figures (all digits) rather than significant digits (digits after the decimal point). Rounding down could be easily accomplished by passing a switch along with the other parameters.

Mike
lex_63de at yahoo dot de
26-Jun-2007 09:33
Here is my little round function. Works nice on php 4.3.11 and 5.0.5

printf("0.285 - %s <br> ",round(0.285,2));      // incorrect result 0.28
printf("1.285 - %s <br> ",round(1.285,2));      // correct result 1.29
printf("1.255 - %s <br><br>",round(1.255,2));   // incorrect result 1.25

printf("0.285 - %s <br> ",myRound(0.285,2));    // incorrect result 0.29
printf("1.285 - %s <br> ",myRound(1.285,2));    // incorrect result 1.29
printf("1.255 - %s <br> ",myRound(1.255,2));    // incorrect result 1.255

function myRound($value,$round=2)
{
    $value *= pow(10.0,$round);
    $value  = floor(floatval($value + 0.6));
    $value /= pow(10.0,$round);

    return($value);
}
bitbrains at yahoo dot com
22-Jun-2007 09:59
Surprisingly, the round() cannot work with 1.255,

echo round(1.255, 2);    echo "<BR>";// 1.25
pjm at pehjota dot com
28-Apr-2007 08:01
In response to maxteiber at gmail dot com, regarding rounding 141.075 to 2 decimal places:

I can justify your computer for rounding it to 141.07. It's following a rounding rule similar to the "significant figures" rules in science. Try rounding 141.0751 or 141.0756.
tom at crysis-online dot com
18-Mar-2007 12:31
I just found out then that even if you round a double (3.7) to an integer (4), it's data type remains as 'double'. So it's always good to use the settype() function when using the round() function to prevent any problems with your scripts.
16-Mar-2007 05:11
With regard to chafy at alo dot bg's not just previous; if the number 5.555 is displayed with sufficient precision (more than about 16 digits) it will probably turn out to have been stored as something like 5.554999999....9997, which would round down to 5.55.

Floating-point numbers should ALWAYS be regarded as being a little bit fuzzy. It's a consequence of the fact that they're stored in binary but humans want them displayed in decimal: you can't write one-tenth exactly as a binary expansion any more than you can write one-seventh exactly as a decimal one.

See the warning note on the floating-point type page.
chafy at alo dot bg
28-Feb-2007 10:13
The function round numbers to a given precision.

function toFixed($number, $round=2)
{
   
    $tempd = $number*pow(10,$round);
    $tempd1 = round($tempd);
    $number = $tempd1/pow(10,$round);
    return $number;
    
}

echo round(5.555,2); //retunr 5.55 - I don\t know why  
echo toFixed(5.555,2);  //return 5.56
pokusman at gmail dot com
30-Jan-2007 11:06
<php?

function RoundPrice($Price) {
 $diff = $Price - floor($Price);
 if ($diff<=0.25) {
  $Price = floor($Price) + 0.25;
 };
 if ($diff>0.25 && $diff<=0.5) {
  $Price = floor($Price) + 0.5;
 };
 if ($diff>0.5 && $diff<=0.75) {
  $Price = floor($Price) + 0.75;
 };
 if ($diff>0.75) {
  $Price = floor($Price) + 1;
 };
 return $Price;
}

$Price = "369.68";
$NewPrice = RoundPrice($Price);  //369.75

echo "Old price: £".$Price." new price £".$NewPrice;

?>

 
Peter Tyson
christof dot moser at actra dot ch
06-Jan-2007 09:32
<?php
function showAmount($amount, $countryData, $vat)
{
   
$amount = $amount*$countryData['kurs'];
    if(
$vat == 1)
    {
       
$amount = $amount*(100+$countryData['mwst'])/100;
    }

   
$rval = 1/$countryData['rundung'];
   
$amount = (round($rval*$amount))/$rval;
   
    return
$amount;
}

$countryData['kurs'] = '1.619000';
$countryData['mwst'] = '7.60';
$countryData['rundung'] = '0.050000';

echo
showAmount('3.976', $countryData, 1);
?>
05-Nov-2006 09:31
Javascript round_number

function roundnumber (n, d) {
  n = n - 0;
  if (d == null) d = 2;
  var f = Math.pow(10, d);
  n += Math.pow(10, - (d + 1));
  n = Math.round(n * f) / f;
  n += Math.pow(10, - (d + 1));
  n += '';
  return d == 0 ? n.substring(0, n.indexOf('.')) :  n.substring(0, n.indexOf('.') + d + 1);
}

PHP round_number;

function roundnumber($n, $d = 0) {
    $n = $n - 0;
    if ($d === NULL) $d = 2;

    $f = pow(10, $d);
    $n += pow(10, - ($d + 1));
    $n = round($n * $f) / $f;
    $n += pow(10, - ($d + 1));
    $n += '';

    if ( $d == 0 ) :
        return substr($n, 0, strpos($n, '.'));
    else : 
    return substr($n, 0, strpos($n, '.') + $d + 1);
endif;
}
dave at koales dot co dot uk
30-Oct-2006 09:39
Note, there is a bug in what appears to be the Windows implementation.  See http://bugs.php.net/bug.php?id=36008 for more information and a fix (convert the number to a string before rounding).
maxteiber at gmail dot com
16-Oct-2006 08:15
the result of this function always depends on the underlying C function. There have been a lot of compiler bugs and floating-point precission problems involving this function. Right now the following code:

<?php
echo round(141.075, 2);
?>

returns:

141.07

on my machine.
So never really trust this function when you do critical calculations like accounting stuff!
Instead: use only integers or use string comparisons.
Hitlers Pet Gerbil
05-Oct-2006 04:47
In response to boonedocks at gmail dot com

Your calculations are slightly incorrect. You only use the formula when the 1/1000 position is equal to 5, otherwise you follow standard rounding proceedures.

I wrote a quick snippet which works with the input as a string, uses inline substrings and substitutions. Works VERY fast.

<?php
function bankers_round ($moneyfloat = null)
{
   
$money_str = sprintf("%01.3f", round($moneyfloat, 3)); // convert to rounded (to the nearest thousandth) string
   
$thous_pos = strlen($money_str)-1;                     // Thousandth string position
   
$hundt_pos = strlen($money_str)-2;                     // Hundredth string position
   
if ($money_str[$thous_pos] === "5") $money_str[$thous_pos] = ((int)$money_str[$hundt_pos] & 1) ? "9" : "0"; // use a bitwise test, its faster than modulus
    // The above statement assists round() by setting the thousandth position to 9 or zero if the hundredth is even or odd (respectively)

   
return round($money_str, 2); // Return rounded value
}

?>

Hitlers Pet Gerbil
ionut dot socol at euromarket dot ro
12-Aug-2006 06:40
My name is Ionut Socol and i'm from Romania

A small script that allow you to round up, round down or just return the integer number.
The $direction value cand be:
0  - rounding down
1 - rounding up
any thing else for returning the integer value

<?php
function rounding($no,$direction)
   {                           
$skip=0;
    if(
is_float($no) and $direction = 1)
       {
      
$exploded = explode(".",$no);
      
$nrr = $exploded[0]+1;     $skip=1;
       }
 
   if(
is_float($no) and $direction = 0)
       {
      
$exploded = explode(".",$no);
      
$nrr = $exploded[0];        $skip=1;
       }

   if(!
is_float($no) and $skip ==1) { $nrr = $nrr; } else { $nrr = floor($nrr); }

     return
$nrr;
   }
?>
12-Jul-2006 01:48
Since everybody here seems to be occupied wanking over their selfmade round() functions, a little note about the actual php-implementation:
If you round() a _very_ small number to a reasonable number of decimals, it will retain its sign! IE:

round(1.4 - 1.4, 4) returns "-0" instead of just "0"!

Dont ask me how to properly get rid of this. Im just gonna cut it off
using preg_replace().
milosz_jablonski at yahoo dot co dot uk
11-May-2006 11:51
function round is more than just fantastic. Why not to use this one instead of creating your own for rounding UP/DOWN

$proc_total1 had a number of values (see 2 examples below)

round($proc_total1)   //$proc_total1=57.1428571429
echo $proc_total1;    //57

round($proc_total1)   //$proc_total1=42.8571428571
echo $proc_total1;    //43

good luck
Mazzu
11-May-2006 04:41
Another correction to the significant digits formula :

($n == 0) ? 0 : round($n, floor(0 - log10(abs($n))) + $sysdigits)

- In order to handle zero and negative numbers
- Use floor() instead of ceil() to do not substract 1
adrianbj
16-Feb-2006 04:19
A simple correction to the significant digits formula posted way below:

round($n, ceil(0 - log10($n)) + $sigdigits - 1);

Note the addition of '-1' to the formula originally posted.
28-Jan-2006 04:41
Instead of writing roundDown() and roundUp() functions in php, you might want to consider floor() and ceil(), as they are probably much, much faster.
reinhard at ess dot co dot at
26-Jan-2006 11:56
the same is true for round_down

function round_down($value){
   list($val,$dummy) = explode(".",$value);
   return $val;
}
reinhard at ess dot co dot at
26-Jan-2006 11:54
I have made the round_up-function much more simpler and useable of any values (float or int) -> if no decimal values then the value is taken else we add one to the value in front of the dot ;)

function round_up($value){
   list($val,$dummy) = explode(".",$value);
   return $dummy?$val+1:$val;
}
elbekko at gmail dot com
24-Jan-2006 05:45
I created a round down function, pretty basic but it should work :P

<?php
function round_down($value)
    {
    if(
is_float($value))
        {
       
$exploded = explode(".",$value);
        return
$exploded[0];
        }
    else
        {
        die(
"Only float values can be entered.");
        }
    }
?>

You could use the same function for rounding up:

<?php
function round_up($value)
    {
    if(
is_float($value))
        {
       
$exploded = explode(".",$value);
        return
$exploded[0] + 1;
        }
    else
        {
        die(
"Only float values can be entered.");
        }
    }
?>
php dot net at cdauth dot de
23-Jan-2006 04:33
Beware that the implementation posted below:
<?php
$number
= 254.51263;
$round = (int)($number+0.5); // 255
?>
does not work with very large numbers.
boonedocks at gmail dot com
14-Jan-2006 05:08
Since PHP no longer does Banker's Rounding, I came up with an implementation here:

http://boonedocks.net/mike/archives/106-Bankers-Rounding-for-PHP.html

It hasn't really been hammered on, so testing and comments are welcome.
adrenalin at bmxstyle dot com
19-Dec-2005 09:42
Oh sorry, I had mistake in a simple version of the script. Here is a working and tested version:

<?php
function divby($val, $by) {
  
  
$val -= $val % $by;
  
   return
$val;
}
?>

But in blackhole's description is a little mistake, because if I try: divby(-23, 10); it will return -20, because $val is negative so the result must be negative too.
adrenalin at bmxstyle dot com
19-Dec-2005 06:31
Here is a simple version of blackhole's script.

<?php
function divby($val, $by) {
 
 
$val -= abs($val) % $by;
  
   return
$val;
}
?>
blackhole at ggot