PHP如何向下舍入到小数点后两位?

时间:2012-09-05 09:06:22

标签: php decimal rounding number-formatting

我需要将PHP中的小数舍入到小数点后两位,以便:

49.955

...变为

49.95

我尝试了 number_format ,但这只是将值四舍五入为 49.96 。我不能使用 substr ,因为数字可能更小(例如7.950)。到目前为止,我一直无法找到答案。

任何帮助都非常感激。

17 个答案:

答案 0 :(得分:75)

这可以有效:floor($number * 100) / 100

答案 1 :(得分:22)

这是一个不使用字符串函数的好方法:

<?php
function floorp($val, $precision)
{
    $mult = pow(10, $precision); // Can be cached in lookup table        
    return floor($val * $mult) / $mult;
}

print floorp(49.955, 2);
?>

另一种选择是在舍入之前减去一个分数:

function floorp($val, $precision)
{
    $half = 0.5 / pow(10, $precision); // Can be cached in a lookup table
    return round($val - $half, $precision);
}

答案 2 :(得分:17)

不幸的是,之前的答案(包括已接受的答案)都不适用于所有可能的输入。

1)sprintf('%1.'.$precision.'f', $val)

失败的精度为2:14.239应该返回14.23(但在这种情况下返回14.24)。

2)floatval(substr($val, 0, strpos($val, '.') + $precision + 1))

失败的精度为0:14应返回14(但在这种情况下返回1)

3)substr($val, 0, strrpos($val, '.', 0) + (1 + $precision))

失败,精度为0:-1应返回-1(但在这种情况下返回&#39; - &#39;)

4)floor($val * pow(10, $precision)) / pow(10, $precision)

虽然我广泛使用了这个,但我最近发现了它的一个缺陷;它也失败了一些价值观。精度为2:2.05应该返回2.05(但在这种情况下返回2.04 !!)

到目前为止,传递所有测试的唯一方法是使用字符串操作。我基于rationalboss的解决方案是:

function floorDec($val, $precision = 2) {
    if ($precision < 0) { $precision = 0; }
    $numPointPosition = intval(strpos($val, '.'));
    if ($numPointPosition === 0) { //$val is an integer
        return $val;
    }
    return floatval(substr($val, 0, $numPointPosition + $precision + 1));
}

此功能适用于正数和负数,以及所需的任何精度。

答案 3 :(得分:6)

将输入乘以100,floor(),然后将结果除以100.

答案 4 :(得分:2)

尝试round()功能

像这样:round($num, 2, PHP_ROUND_HALF_DOWN);

答案 5 :(得分:2)

function roundDown($decimal, $precision)
{
    $sign = $decimal > 0 ? 1 : -1;
    $base = pow(10, $precision);
    return floor(abs($decimal) * $base) / $base * $sign;
}

// Examples
roundDown(49.955, 2);           // output: 49.95
roundDown(-3.14159, 4);         // output: -3.1415
roundDown(1000.000000019, 8);   // output: 1000.00000001

此函数可以任意精度使用正负小数。

此处的代码示例:http://codepad.org/1jzXjE5L

答案 6 :(得分:1)

我认为有一个很简单的方法可以实现:

$rounded = bcdiv($val, 1, $precision);

这里是working example。您需要安装BCMath,但我认为它通常与PHP安装捆绑在一起。 :)Here is the documentation

答案 7 :(得分:0)

对于有需要的人,我使用了一些技巧来克服数学函数故障,例如floor或 intval(9.7 * 100)= 969 很奇怪。

function floor_at_decimals($amount, $precision = 2)
{
    $precise = pow(10, $precision);
    return floor(($amount * $precise) + 0.1) / $precise;
}

因此,添加少量(无论如何都会降低)可以以某种方式解决该问题。

答案 8 :(得分:0)

基于@huysentruitw和@Alex的答案,我想出了以下应该可以解决问题的功能。

它通过了Alex答案中给出的所有测试(这是不可能的原因),并基于huysentruitw的答案。

function trim_number($number, $decimalPlaces) {
    $delta = (0 <=> $number) * (0.5 / pow(10, $decimalPlaces));
    $result = round($number + $delta, $decimalPlaces);
    return $result ?: 0; // get rid of negative zero
}

关键是要在原始数字符号的基础上增加或减少增量,以支持对负数也进行修整。 最后一件事是摆脱负零(-0),因为这可能是有害的行为。

Link to "test" playground

编辑:bcdiv似乎是要解决的方法。

// round afterwards to cast 0.00 to 0
// set $divider to 1 when no division is required
round(bcdiv($number, $divider, $decimalPlaces), $decimalPlaces);

答案 9 :(得分:0)

您可以使用bcdiv PHP函数。

bcdiv(49.955, 1, 2)

答案 10 :(得分:0)

Reference

答案 11 :(得分:0)

使用正则表达式的替代解决方案,适用于所有正数或负数,整数或小数:

if (preg_match('/^-?(\d+\.?\d{1,2})\d*$/', $originalValue, $matches)){
    $roundedValue = $matches[1];
} else {
    throw new \Exception('Cannot round down properly '.$originalValue.' to two decimal places');
}

答案 12 :(得分:0)

您可以使用:

$num = 49.9555;
echo substr($num, 0, strpos($num, '.') + 3);

答案 13 :(得分:0)

使用格式化输出

sprintf("%1.2f",49.955) //49.95

DEMO

答案 14 :(得分:-2)

这个怎么样?

$value = 49.955;

echo intval( $value * 100 ) / 100;

Here is a demo

答案 15 :(得分:-2)

sprintf("%1.2f",49.955) //49.95

如果你需要在没有舍入的情况下截断小数 - 这是不合适的,因为它会在49.95 5 结束时正常工作,如果数字更多,例如49.95 7 它会四舍五入到49.96
对我而言,Lght对地板的回答是最普遍的。

答案 16 :(得分:-4)

你试过round($val,2)吗?

有关round()功能

的更多信息