round()
(PHP 4, PHP 5, PHP 7)
对浮点数进行四舍五入
说明
round(float $val[,int $precision= 0[,int $mode= PHP_ROUND_HALF_UP]]):float
返回将$val根据指定精度$precision(十进制小数点后数字的数目)进行四舍五入的结果。$precision也可以是负数或零(默认值)。
Note:PHP 默认不能正确处理类似"12,300.2"的字符串。见字符串转换为数值。
参数
- $val
要处理的值
- $precision
可选的十进制小数点后数字的数目。
- $mode
以下之一:
PHP_ROUND_HALF_UP
、PHP_ROUND_HALF_DOWN
PHP_ROUND_HALF_EVEN
或PHP_ROUND_HALF_ODD
返回值
四舍五入后的值
范例
Example #1round()例子
<?php echo round(3.4); // 3 echo round(3.5); // 4 echo round(3.6); // 4 echo round(3.6, 0); // 4 echo round(1.95583, 2); // 1.96 echo round(1241757, -3); // 1242000 echo round(5.045, 2); // 5.05 echo round(5.055, 2); // 5.06 ?>
Example #2$mode例子
<?php echo round(9.5, 0, PHP_ROUND_HALF_UP); // 10 echo round(9.5, 0, PHP_ROUND_HALF_DOWN); // 9 echo round(9.5, 0, PHP_ROUND_HALF_EVEN); // 10 echo round(9.5, 0, PHP_ROUND_HALF_ODD); // 9 echo round(8.5, 0, PHP_ROUND_HALF_UP); // 9 echo round(8.5, 0, PHP_ROUND_HALF_DOWN); // 8 echo round(8.5, 0, PHP_ROUND_HALF_EVEN); // 8 echo round(8.5, 0, PHP_ROUND_HALF_ODD); // 9 ?>
更新日志
版本 | 说明 |
---|---|
5.3.0 | 引入了$mode参数 |
5.2.7 | round()的内部运作修改符合 C99 的标准。 |
参见
ceil()
进一法取整floor()
舍去法取整number_format()
以千位分隔符方式格式化一个数字
In my opinion this function lacks two flags: - PHP_ROUND_UP - Always round up. - PHP_ROUND_DOWN - Always round down. In accounting, it's often necessary to always round up, or down to a precision of thousandths. <?php function round_up($number, $precision = 2) { $fig = (int) str_pad('1', $precision, '0'); return (ceil($number * $fig) / $fig); } function round_down($number, $precision = 2) { $fig = (int) str_pad('1', $precision, '0'); return (floor($number * $fig) / $fig); } ?>
If you have negative zero and you need return positive number simple add +0: $number = -2.38419e-07; var_dump(round($number,1));//float(-0) var_dump(round($number,1) + 0);//float(0)
As PHP doesn't have a a native number truncate function, this is my solution - a function that can be usefull if you need truncate instead round a number. <?php /** * Truncate a float number, example: <code>truncate(-1.49999, 2); // returns -1.49 * truncate(.49999, 3); // returns 0.499 * </code> * @param float $val Float number to be truncate * @param int f Number of precision * @return float */ function truncate($val, $f="0") { if(($p = strpos($val, '.')) !== false) { $val = floatval(substr($val, 0, $p + 1 + $f)); } return $val; } ?> Originally posted in http://stackoverflow.com/a/12710283/1596489
I discovered that under some conditions you can get rounding errors with round when converting the number to a string afterwards. To fix this I swapped round() for number_format(). Unfortunately i cant give an example (because the number cant be represented as a string !) essentially I had round(0.688888889,2); which would stay as 0.68888889 when printed as a string. But using number_format it correctly became 0.69.
PHP 5.3, 5.4, 5.5 <?php $fInfinty = pow(1000, 1000); // float(INF) $fResult = round(123.456, $fInfinty); // double(123) ?> PHP 5.6 <?php $fInfinty = pow(1000, 1000); // float(INF) $fResult = round(123.456, $fInfinty); // float(0) ?> PHP 7 <?php $fInfinty = pow(1000, 1000); // float(INF) $fResult = round(123.456, $fInfinty); // null ?>
If you'd only want to round for displaying variables (not for calculating on the rounded result) then you should use printf with the float: <?php printf ("%6.2f",3.39532); ?> This returns: 3.40 .
function mround($val, $f=2, $d=6){ return sprintf("%".$d.".".$f."f", $val); } echo mround(34.89999); //34.90
Here is function that rounds to a specified increment, but always up. I had to use it for price adjustment that always went up to $5 increments. <?php function roundUpTo($number, $increments) { $increments = 1 / $increments; return (ceil($number * $increments) / $increments); } ?>
This function will let you round to an arbitrary non-zero number. Zero of course causes a division by zero. <?php function roundTo($number, $to){ return round($number/$to, 0)* $to; } echo roundTo(87.23, 20); //80 echo roundTo(-87.23, 20); //-80 echo roundTo(87.23, .25); //87.25 echo roundTo(.23, .25); //.25 ?>
Here's a function to round to an arbitary number of significant digits. Don't confuse it with rounding to a negative precision - that counts back from the decimal point, this function counts forward from the Most Significant Digit. ex: <?php round(1241757, -3); // 1242000 RoundSigDigs(1241757, 3); // 1240000 ?> Works on negative numbers too. $sigdigs should be >= 0 <?php function RoundSigDigs($number, $sigdigs) { $multiplier = 1; while ($number < 0.1) { $number *= 10; $multiplier /= 10; } while ($number >= 1) { $number /= 10; $multiplier *= 10; } return round($number, $sigdigs) * $multiplier; } ?>
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
this function (as all mathematical operators) takes care of the setlocale setting, resulting in some weirdness when using the result where the english math notation is expected, as the printout of the result in a width: style attribute! <?php $a=3/4; echo round($a, 2); // 0.75 setlocale(LC_ALL, 'it_IT@euro', 'it_IT', 'it'); $b=3/4; echo round($b,2); // 0,75 ?>
Excel-like ROUNDUP function: public static function round_up($value, $places) { $mult = pow(10, abs($places)); return $places < 0 ? ceil($value / $mult) * $mult : ceil($value * $mult) / $mult; } echo round_up(12345.23, 1); // 12345.3 echo round_up(12345.23, 0); // 12346 echo round_up(12345.23, -1); // 12350 echo round_up(12345.23, -2); // 12400 echo round_up(12345.23, -3); // 13000 echo round_up(12345.23, -4); // 20000
Unexpected result or misunderstanding (php v5.5.9) <?php echo round(1.55, 1, PHP_ROUND_HALF_DOWN); // 1.5 echo round(1.551, 1, PHP_ROUND_HALF_DOWN); //1.6 ?>
round() will sometimes return E notation when rounding a float when the amount is small enough - see https://bugs.php.net/bug.php?id=44223 . Apparently it's a feature. To work around this "feature" when converting to a string, surround your round statement with an sprintf: sprintf("%.10f", round( $amountToBeRounded, 10));
When you have a deal with money like dollars, you need to display it under this condition: -format all number with two digit decimal for cents. -divide 1000 by , -round half down for number with more than two decimal I approach it using round function inside the number_format function: number_format((float)round( 625.371 ,2, PHP_ROUND_HALF_DOWN),2,'.',',') // 625.37 number_format((float)round( 625.379 ,2, PHP_ROUND_HALF_DOWN),2,'.',',') // 625.38 number_format((float)round( 1211.20 ,2, PHP_ROUND_HALF_DOWN),2,'.',',') // 1,211.20 number_format((float)round( 625 ,2, PHP_ROUND_HALF_DOWN),2,'.',',') // 625.00
Solving round_down() problem: ----------------------------- Use of <?php floor(pow(10, $precision) * $value) / pow(10, $precision); ?> fails in some cases, e.g. round_down(2.05, 2) gives incorrect 2.04. Here is a "string" solution (https://stackoverflow.com/a/26491492/1245149) of the problem (a negative precision is not covered): <?php function round_down($value, $precision) { $value = (float)$value; $precision = (int)$precision; if ($precision < 0) { $precision = 0; } $decPointPosition = strpos($value, '.'); if ($decPointPosition === false) { return $value; } return (float)(substr($value, 0, $decPointPosition + $precision + 1)); } ?> Solving round_up() problem: --------------------------- Use of <?php ceil(pow(10, $precision) * $value) / pow(10, $precision);?> fails in some cases, e.g. round_up(2.22, 2) gives incorrect 2.23 (https://stackoverflow.com/a/8239620/1245149). Adapting the above round_down() "string" solution I have got this result (a negative precision is not covered): <?php 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.
It should just be noted that what is called "precision" on this page is more correctly called accuracy; precision is the total number of significant digits on both sides of the decimal point, while accuracy is the number of digits to the right of the point. It's a common confusion.
Note that PHP 5.3 didn't just introduce $mode, it rewrote the rounding implementation completely to eliminate many kinds of rounding errors common to rounding floating point values. That's why round() gives you the correct result even when floor/ceil don't. For example, floor(0.285 * 100 + 0.5) VS round(0.285*100 + 0.5). First one gives 28, second one gives 29. More details here: https://wiki.php.net/rfc/rounding
/** * Round to first significant digit * +N to +infinity * -N to -infinity * */ function round1stSignificant ( $N ) { if ( $N === 0 ) { return 0; } $x = floor ( log10 ( abs( $N ) ) ); return ( $N > 0 ) ? ceil( $N * pow ( 10, $x * -1 ) ) * pow( 10, $x ) : floor( $N * pow ( 10, $x * -1 ) ) * pow( 10, $x ); } echo round1stSignificant( 39144818 ) . PHP_EOL; echo round1stSignificant( 124818 ) . PHP_EOL; echo round1stSignificant( 0.07468 ) . PHP_EOL; echo round1stSignificant( 0 ) . PHP_EOL; echo round1stSignificant( -0.07468 ) . PHP_EOL; /** * Output * * 40000000 * 200000 * 0.08 * 0 * -0.08 * */
This functions return ceil($nb) if the double or float value is bigger than "$nb.5" else it's return floor($nb) <?php function arounds_int($nb) { if(!is_numeric($nb)) { return false; } $sup = round($nb); $inf = floor($nb); $try = (double) $inf . '.5' ; if($nb > $try) { return $sup; } return $inf; } ?>
Here is a short neat function to round minutes (hour) ... <?php function minutes_round ($hour = '14:03:32', $minutes = '5', $format = "H:i") { // by Femi Hasani [www.vision.to] $seconds = strtotime($hour); $rounded = round($seconds / ($minutes * 60)) * ($minutes * 60); return date($format, $rounded); } ?> You decide to round to nearest minute ... example will produce : 14:05
In case someone will need a "graceful" rounding (that changes it's precision to get a non 0 value) here's a simple function: function gracefulRound($val, $min = 2, $max = 4) { $result = round($val, $min); if ($result == 0 && $min < $max) { return gracefulRound($val, ++$min, $max); } else { return $result; } } Usage: $_ = array(0.5, 0.023, 0.008, 0.0007, 0.000079, 0.0000048); foreach ($_ as $val) { echo "{$val}: ".gracefulRound($val)."\n"; } Output: 0.5: 0.5 0.023: 0.02 0.008: 0.01 0.0007: 0.001 0.000079: 0.0001 0.0000048: 0
To round any number to a given number of significant digits, use log10 to find out its magnitude: <?php round($n, ceil(0 - log10($n)) + $sigdigits); ?> Or when you have to display a per-unit price which may work out to be less than a few cents/pence/yen you can use: <?php // $exp = currency decimal places - 0 for Yen/Won, 2 for most others $dp = ceil(0 - log10($n)) + $sigdigits; $display = number_format($amount, ($exp>$dp)?$exp:$dp); ?> This always displays at least the number of decimal places required by the currency, but more if displaying the unit price with precision requires it - eg: 'English proofreading from $0.0068 per word', 'English beer from $6.80 per pint'.
This function has strange. behaviors: <?php echo round(0.045, 2); // 0.05 echo round(0.45, 1); // 0.5 echo round(1.045-1, 2); // 0.04 !!! echo round(1.45-1, 1); // 0.5
Because this function is missing round up and round down constants and the top note doesn't really show you how to round up or down to the nearest number, here is an easy way to always round up or always round down to the nearest number. int is the number you want to round n is the nearest number you want rounded to. Round up to the nearest number function round_up($int, $n) { return ceil($int / $n) * $n; } And to round down to the nearest number function round_down(int, $n) { return floor($int / $n) * $n; }
Beware strange behaviour if number is negative and precision is bigger than the actual number of digits after comma. round(-0.07, 4); returns -0.07000000000000001 So if you validate it against a regular expression requiring the maximum amount of digits after comma, you'll get into trouble.
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.
Since the mode parameter for options like PHP_ROUND_HALF_UP is available as of PHP 5.3, here is an alternative for ceiling: <?php echo 252 / 40; // 6.3 ?> If I round this: <?php echo round(252 / 40); // 6 ?> You can also use a ceil (which might be useful for pagination): <?php echo ceil(252/40); // 7 ?> [Edited by: googleguy@php.net for clarity]
Formats a number to the specified number of significant figures. <?php /** * Formats numbers to the specified number of significant figures. * * @author Bevan Rudge, Drupal.geek.nz * * @param number $number * The number to format. * @param integer $sf * The number of significant figures to round and format the number to. * @return string * The rounded and formatted number. */ function format_number_significant_figures($number, $sf) { // How many decimal places do we round and format to? // @note May be negative. $dp = floor($sf - log10(abs($number))); // Round as a regular number. $number = round($number, $dp); // Leave the formatting to format_number(), but always format 0 to 0dp. return number_format($number, 0 == $number ? 0 : $dp); } ?>
$a = .9; $b = .8; $d = .1; $e = .2; $x = $a-$b; $y = $e-$d; $f = round($x,2); echo $f; if($f==$y){ echo "ok"; }