PHP Conference Japan 2024

round

(PHP 4, PHP 5, PHP 7, PHP 8)

round將浮點數四捨五入

說明

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

num 的值四捨五入到指定的 precision(小數點後的位數)。precision 也可以是負數或零(預設值)。

參數

num

要四捨五入的值。

precision

要四捨五入的小數位數(可選)。

如果 precision 為正數,則 num 會四捨五入到小數點後 precision 個有效位數。

如果 precision 為負數,num 會在小數點前捨入至 precision 個有效位數,也就是捨入至 pow(10, -$precision) 的最接近倍數。例如,precision 為 -1 時,num 會捨入至十位數;precision 為 -2 時,會捨入至百位數,依此類推。

模式

使用以下常數之一來指定捨入模式。

常數 說明
PHP_ROUND_HALF_UP num 恰好位於中間值時,將其捨入遠離零,例如將 1.5 捨入為 2,將 -1.5 捨入為 -2。
PHP_ROUND_HALF_DOWN num 恰好位於中間值時,將其捨入朝向零,例如將 1.5 捨入為 1,將 -1.5 捨入為 -1。
PHP_ROUND_HALF_EVEN num 恰好位於中間值時,將其捨入至最接近的偶數值,例如將 1.5 和 2.5 都捨入為 2。
PHP_ROUND_HALF_ODD num 恰好位於中間值時,將其捨入至最接近的奇數值,例如將 1.5 捨入為 1,將 2.5 捨入為 3。

回傳值

捨入至指定 precision 的值,以 浮點數 格式返回。

更新日誌

版本 說明
8.0.0 num 不再接受支援數值轉換的內部物件。

範例

範例 #1 round() 範例

<?php
var_dump
(round(3.4));
var_dump(round(3.5));
var_dump(round(3.6));
var_dump(round(3.6, 0));
var_dump(round(5.045, 2));
var_dump(round(5.055, 2));
var_dump(round(345, -2));
var_dump(round(345, -3));
var_dump(round(678, -2));
var_dump(round(678, -3));
?>

以上範例將輸出

float(3)
float(4)
float(4)
float(4)
float(5.05)
float(5.06)
float(300)
float(0)
float(700)
float(1000)

範例 #2 precision 如何影響浮點數

<?php
$number
= 135.79;

var_dump(round($number, 3));
var_dump(round($number, 2));
var_dump(round($number, 1));
var_dump(round($number, 0));
var_dump(round($number, -1));
var_dump(round($number, -2));
var_dump(round($number, -3));
?>

以上範例將輸出

float(135.79)
float(135.79)
float(135.8)
float(136)
float(140)
float(100)
float(0)

範例 #3 mode 範例

<?php
echo '使用 9.5 的進位模式' . PHP_EOL;
var_dump(round(9.5, 0, PHP_ROUND_HALF_UP));
var_dump(round(9.5, 0, PHP_ROUND_HALF_DOWN));
var_dump(round(9.5, 0, PHP_ROUND_HALF_EVEN));
var_dump(round(9.5, 0, PHP_ROUND_HALF_ODD));

echo
PHP_EOL;
echo
'使用 8.5 的進位模式' . PHP_EOL;
var_dump(round(8.5, 0, PHP_ROUND_HALF_UP));
var_dump(round(8.5, 0, PHP_ROUND_HALF_DOWN));
var_dump(round(8.5, 0, PHP_ROUND_HALF_EVEN));
var_dump(round(8.5, 0, PHP_ROUND_HALF_ODD));
?>

以上範例將輸出

Rounding modes with 9.5
float(10)
float(9)
float(10)
float(9)

Rounding modes with 8.5
float(9)
float(8)
float(8)
float(9)

範例 #4 使用 精確度 參數的 模式 範例

<?php
echo '使用 PHP_ROUND_HALF_UP 進行一位小數的精度捨入' . PHP_EOL;
var_dump(round( 1.55, 1, PHP_ROUND_HALF_UP));
var_dump(round(-1.55, 1, PHP_ROUND_HALF_UP));

echo
PHP_EOL;
echo
'使用 PHP_ROUND_HALF_DOWN 進行一位小數的精度捨入' . PHP_EOL;
var_dump(round( 1.55, 1, PHP_ROUND_HALF_DOWN));
var_dump(round(-1.55, 1, PHP_ROUND_HALF_DOWN));

echo
PHP_EOL;
echo
'使用 PHP_ROUND_HALF_EVEN 進行一位小數的精度捨入' . PHP_EOL;
var_dump(round( 1.55, 1, PHP_ROUND_HALF_EVEN));
var_dump(round(-1.55, 1, PHP_ROUND_HALF_EVEN));

echo
PHP_EOL;
echo
'使用 PHP_ROUND_HALF_ODD 進行一位小數的精度捨入' . PHP_EOL;
var_dump(round( 1.55, 1, PHP_ROUND_HALF_ODD));
var_dump(round(-1.55, 1, PHP_ROUND_HALF_ODD));
?>

以上範例將輸出

Using PHP_ROUND_HALF_UP with 1 decimal digit precision
float(1.6)
float(-1.6)

Using PHP_ROUND_HALF_DOWN with 1 decimal digit precision
float(1.5)
float(-1.5)

Using PHP_ROUND_HALF_EVEN with 1 decimal digit precision
float(1.6)
float(-1.6)

Using PHP_ROUND_HALF_ODD with 1 decimal digit precision
float(1.5)
float(-1.5)

另請參閱

  • ceil() - 無條件進位至最接近的整數
  • floor() - 無條件捨去至最接近的整數
  • number_format() - 以千位分隔符號格式化數字

新增筆記

使用者貢獻的筆記 29 則筆記

takingsides at gmail dot com
10 年前
在我看來,這個函式缺少兩個旗標

- PHP_ROUND_UP - 永遠向上取整。
- PHP_ROUND_DOWN - 永遠向下取整。

在會計中,經常需要精確到千分位並永遠向上或向下取整。

<?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);
}
?>
depaula at unilogica dot com
7 年前
由於 PHP 沒有原生數字截斷函式,這是我提供的解決方案 - 如果您需要截斷而不是捨入數字,這個函式會很有用。

<?php
/**
* 截斷浮點數,範例: <code>truncate(-1.49999, 2); // 返回 -1.49
* truncate(.49999, 3); // 返回 0.499
* </code>
* @param float $val 要截斷的浮點數
* @param int f 精度位數
* @return float
*/
function truncate($val, $f="0")
{
if((
$p = strpos($val, '.')) !== false) {
$val = floatval(substr($val, 0, $p + 1 + $f));
}
return
$val;
}
?>

原始發佈於 http://stackoverflow.com/a/12710283/1596489
slimusgm at gmail dot com
10 年前
如果您有負零且需要返回正數,只需加 +0

$number = -2.38419e-07;
var_dump(round($number,1));//float(-0)
var_dump(round($number,1) + 0);//float(0)
Mojo urk
6 年前
解決 round_down() 的問題
-----------------------------
使用 `<?php floor(pow(10, $precision) * $value) / pow(10, $precision); ?> 在某些情況下會失敗,例如 round_down(2.05, 2) 會給出錯誤的 2.04。
這是該問題的一個「字串」解決方案(https://stackoverflow.com/a/26491492/1245149)(負的精確度未涵蓋)

<?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));
}
?>

解決 round_up() 的問題
---------------------------
使用 `<?php ceil(pow(10, $precision) * $value) / pow(10, $precision);?> 在某些情況下會失敗,例如 round_up(2.22, 2) 會給出錯誤的 2.23(https://stackoverflow.com/a/8239620/1245149)。
修改上述 round_down() 的「字串」解決方案,我得到了以下結果(負的精確度未涵蓋)

<?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); // 這樣是否總是得到正確的結果?
}
else {
$ceilValue = $floorValue;
}
return
$ceilValue;
}
?>

我不確定它是否完美無缺,但至少它解決了上述提到的錯誤。我沒有做二進位到十進位數學分析,但如果 `$floorValue + pow(10, 0 - $precision)` 的運算結果
總是如預期,那應該就沒問題。
serg at kalachev dot ru
10 年前
類似 Excel 的 ROUNDUP 函式

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
jongbumi at gmail dot com
8 年前
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
?>
djcox99 at googlemail dot com
10 年前
我發現,在某些情況下,使用 round 函式並在之後將數字轉換為字串時,可能會出現捨入錯誤。

為了修正這個問題,我將 round() 換成了 number_format()。

很遺憾,我無法提供一個範例(因為該數字無法以字串表示!)

基本上,我的程式碼是 round(0.688888889,2);

當以字串列印時,它會維持 0.68888889。

但使用 number_format() 後,它正確地變成了 0.69。
esion99 at gmail dot com
10 年前
非預期的結果或誤解 (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

?>
christian at deligant dot net
13 年前
這個函式(如同所有數學運算子)會受到 setlocale 設定的影響,當在需要使用英文數學符號的結果時,例如在 width: 樣式屬性中列印結果,就會產生一些奇怪的現象!

<?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
?>
twan at ecreation dot nl
24 年前
如果您只想為了顯示變數而進行四捨五入(而不是為了根據四捨五入的結果進行計算),那麼您應該使用 printf 搭配浮點數格式。

<?php printf ("%6.2f",3.39532); ?>

這會返回:3.40。
craft at ckdevelop dot org
10 年前
function mround($val, $f=2, $d=6){
return sprintf("%".$d.".".$f."f", $val);
}

echo mround(34.89999); //34.90
匿名
14 年前
以下是一個將數字無條件進位到指定增量的函式。我需要用它來調整價格,使其總是進位到 5 美元的倍數。

<?php
function roundUpTo($number, $increments) {
$increments = 1 / $increments;
return (
ceil($number * $increments) / $increments);
}
?>
michaeldnelson dot mdn at gmail dot com
15 年前
這個函式可以讓你將數字四捨五入到任意非零數字。當然,零會導致除以零的錯誤。

<?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
?>
greghenle at gmail dot com
8 年前
/**
* 四捨五入到第一個有效位數
* +N 到 +無限大
* -N 到 -無限大
*
*/
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;

/**
* 輸出
*
* 40000000
* 200000
* 0.08
* 0
* -0.08
*
*/
dastra
12 年前
當要四捨五入的浮點數值夠小時,round() 有時會回傳科學記號表示法 - 詳見 https://bugs.php.net/bug.php?id=44223。 顯然這是一個特性。

要解決這個在轉換為字串時的「特性」,請用 sprintf 包住你的 round 陳述式

sprintf("%.10f", round( $amountToBeRounded, 10));
php at silisoftware dot com
22 年前
這是一個將數字四捨五入到任意有效位數的函式。不要將它與四捨五入到負精度混淆 - 負精度是從小數點往回算,而這個函式是從最高有效位數往前算。

例如

<?php
round
(1241757, -3); // 1242000
RoundSigDigs(1241757, 3); // 1240000
?>

也能處理負數。$sigdigs 應該 >= 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;
}
?>
martinr at maarja dot net
16 年前
請注意,此函數輸出的格式也取決於您的地區設定。例如,如果您將地區設定為使用逗號分隔小數位的國家/地區,則此函數的輸出也會使用逗號而不是點。

當您將捨入後的浮點數輸入需要使用點分隔小數位的資料庫時,這可能會產生問題。

實際操作範例
<?php
echo round('3.5558', 2);
setlocale(constant('LC_ALL'), 'et_EE.UTF-8');
echo
'<br />'. round('3.5558', 2);
?>

輸出結果為
3.56
3,56
匿名
8 年前
請注意,PHP 5.3 不僅引入了 $mode 參數,還完全重寫了捨入的實作方式,以消除許多捨入浮點值常見的捨入錯誤。

這就是為什麼即使 floor/ceil 無法得到正確結果時,round() 仍能提供正確結果的原因。
例如,floor(0.285 * 100 + 0.5) 與 round(0.285*100 + 0.5)。前者結果為 28,後者結果為 29。

更多細節請參考:https://wiki.php.net/rfc/rounding
feha at vision dot to
14 年前
這裡有一個簡潔的函數用於捨入分鐘(小時)...

<?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);
}

?>

您決定要四捨五入到最接近的分鐘數…
範例會產生:14:05
goreyshi at gmail dot com
6 年前
當您處理金錢(例如美元)時,您需要在以下條件下顯示它
-所有數字格式化為兩位小數,表示美分。
-以 , 分隔千位。
-超過兩位小數的數字,採用無條件捨去法進行四捨五入。

我使用 number_format 函式內的 round 函式來處理它

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
omnibus at omnibus dot edu dot pl
14 年前
如果數字為負數且精度大於逗號後的實際位數,請注意其奇怪的行為。

round(-0.07, 4);

返回

-0.07000000000000001

因此,如果您使用需要逗號後最大位數的正規表示式來驗證它,您將會遇到麻煩。
Astro
4 年前
好的,我的函式的最終版本

function NumberPrecision($n, $precision=0, $is_round=true)
{
if ($is_round)
{
$r = 5 * pow(10, -($precision+1));
$n += (($n < 0) ? -$r : $r);
}

$comma = '.';

$r = 5 * pow(10, -($precision+2));
$n += (($n > 0) ? -$r : $r);
$n = number_format($n, $precision+1, $comma, '');

$n .= $comma;
list($n, $frac) = explode($comma, $n, 2);
$n = rtrim(rtrim($n, $comma) . $comma . substr($frac, 0, $precision), $comma);
return ($n);
}

在某些情況下,當內建函式(如 round() 或 number_format())返回意外結果時,它會很有用。適用於正數和負數、零、像 1/12、0.3 之類的數字、科學記數法表示的數字等。
terry at scribendi dot com
20 年前
要將任何數字四捨五入到給定的有效位數,請使用 log10 找出其數量級

<?php round($n, ceil(0 - log10($n)) + $sigdigits); ?>

或者,當您必須顯示每單位價格,而該價格可能低於幾美分/便士/日元時,您可以使用

<?php
// $exp = 貨幣小數位數 - 日圓/韓圜為 0,大多數其他貨幣為 2
$dp = ceil(0 - log10($n)) + $sigdigits;
$display = number_format($amount, ($exp>$dp)?$exp:$dp);
?>

這總是會顯示至少貨幣所需的小數位數,但如果需要精確顯示單價時,則會顯示更多位數 - 例如:「英文校對,每字 0.0068 美元起」、「英國啤酒,每品脫 6.80 美元起」。
匿名
15 年前
如果雙精度或浮點數值大於「$nb.5」,此函數會返回 ceil($nb),否則返回 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;
}
?>
匿名
7 年前
這個函數的行為很奇怪。

<?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
Hayley Watson
5 年前
應該要注意的是,此頁面上所說的「精確度 (precision)」更正確的說法應該是「準確度 (accuracy)」;精確度是小數點兩側有效數字的總數,而準確度是小數點右側的位數。這是一個常見的混淆。
spectrumcat at gmail dot com
10 年前
如果有人需要「優雅的」四捨五入(更改其精確度以獲得非 0 值),這裡有一個簡單的函數

function gracefulRound($val, $min = 2, $max = 4) {
$result = round($val, $min);
if ($result == 0 && $min < $max) {
return gracefulRound($val, ++$min, $max);
} else {
return $result;
}
}

用法
$_ = array(0.5, 0.023, 0.008, 0.0007, 0.000079, 0.0000048);
foreach ($_ as $val) {
echo "{$val}: ".gracefulRound($val)."\n";
}

輸出
0.5: 0.5
0.023: 0.02
0.008: 0.01
0.0007: 0.001
0.000079: 0.0001
0.0000048: 0
maxteiber at gmail dot com
18 年前
這個函式的結果總是取決於底層的 C 函式。一直以來,有很多編譯器錯誤和涉及此函式的浮點精度問題。目前,以下程式碼在我的機器上:

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

返回

141.07


所以,當你在進行關鍵計算(例如會計事務)時,永遠不要完全相信這個函式!
建議:只使用整數或使用字串比較。
php at persignum dot com
9 年前
因為這個函式缺少向上取整和向下取整的常數,而且頂部的說明並沒有真正顯示如何向上或向下取整到最接近的數字,以下提供一個簡單的方法來總是向上或向下取整到最接近的數字。

int 是你要取整的數字

n 是你要取整到的最接近的數字。

向上取整到最接近的數字

function round_up($int, $n) {
return ceil($int / $n) * $n;
}

向下取整到最接近的數字

function round_down(int, $n) {


return floor($int / $n) * $n;
}
To Top