【发布时间】:2011-01-05 16:21:36
【问题描述】:
我似乎无法弄清楚如何始终在 PHP 中进行四舍五入。 ceil() 将是显而易见的选择,但我需要 round() 提供的第二个参数“precision”相同的功能。这是一个例子:
我需要始终将数字四舍五入,以便我可以根据图表的参数计算等数。
【问题讨论】:
我似乎无法弄清楚如何始终在 PHP 中进行四舍五入。 ceil() 将是显而易见的选择,但我需要 round() 提供的第二个参数“precision”相同的功能。这是一个例子:
我需要始终将数字四舍五入,以便我可以根据图表的参数计算等数。
【问题讨论】:
来自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);
}
【讨论】:
ceiling(77.4, 2) === 77.41。功能坏了。
ceiling( 77.400 , 2 )
77.4 与77.400 等相同,但77.4 的上限根本不应该产生77.41。
其中一些答案存在浮点运算问题,如this answer 所示,可能会失败。对于所有情况下的防弹解决方案,请使用这些:
/**
* 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);
}
【讨论】:
由于版本 ceil(pow(10, $precision) * $value) / pow(10, $precision); 在某些情况下会失败,例如如here 所述,round_up(2.22, 2) 给出了不正确的 2.23,因此我已将 string solution for round_down() 调整为我们的 round_up() 问题。这是结果(不包括负精度):
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;
}
我不知道它是防弹的,但至少它消除了上面提到的失败。我没有进行二进制到十进制的数学分析,但如果 $floorValue + pow(10, 0 - $precision) 有效
总是如预期那样应该没问题。如果您发现一些失败的案例,请告诉我 - 我们应该寻找另一种解决方案 :)
【讨论】:
你可以除以 10,ceil();然后乘以十
【讨论】:
echo 10*ceil($number/10);
【讨论】:
另一个精确的 ceil 解决方案,没有 pow,看起来两边都可以工作 9 位:
$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";
}
}
【讨论】: