54

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

49.955

变成……

49.95

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

非常感谢任何帮助。

4

16 回答 16

100

这可以工作:floor($number * 100) / 100

于 2012-09-05T09:13:14.403 回答
24

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

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(但在这种情况下返回“-”)

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

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

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

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

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

于 2014-10-21T16:19:22.537 回答
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);
}
于 2012-09-05T09:12:38.297 回答
11

我认为有一种非常简单的方法可以实现这一点:

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

这是一个工作示例。您需要安装 BCMath,但我认为它通常与 PHP 安装捆绑在一起。:)这是文档

于 2019-03-19T10:48:21.270 回答
7

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

于 2012-09-05T09:13:04.687 回答
7
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

于 2016-02-20T00:51:49.950 回答
4

您可以使用 bcdiv PHP 函数。

bcdiv(49.955, 1, 2)
于 2019-03-19T10:55:14.573 回答
3

试试这个round()功能

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

于 2012-09-05T09:10:08.220 回答
3

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

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

所以添加少量(无论如何都会被搁置)以某种方式解决了这个问题。

于 2019-11-20T22:39:21.550 回答
1
function floorToPrecision($val, $precision = 2) {
        return floor(round($val * pow(10, $precision), $precision)) / pow(10, $precision);
    }
于 2019-03-11T10:26:41.103 回答
0

使用格式化输出

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

演示

于 2012-09-05T09:09:27.327 回答
0

您可以使用:

$num = 49.9555;
echo substr($num, 0, strpos($num, '.') + 3);
于 2012-09-05T09:09:36.183 回答
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');
}
于 2017-11-30T20:33:28.647 回答
0

基于@huysentruitw 和@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
}

关键是在原始数字符号的基础上加减delta,以支持修剪负数。最后一件事是去掉负零 (-0),因为这可能是不受欢迎的行为。

链接到“测试”游乐场

编辑: bcdiv 似乎是要走的路。

// round afterwards to cast 0.00 to 0
// set $divider to 1 when no division is required
round(bcdiv($number, $divider, $decimalPlaces), $decimalPlaces);
于 2019-09-02T12:41:14.777 回答
-2
sprintf("%1.2f",49.955) //49.95

如果您需要在不四舍五入的情况下截断小数 - 这是不合适的,因为它会在最后 49.95 5之前正常工作,如果数字更多,例如 49.95 7,它将四舍五入到 49.96
在我看来,Lght 的答案是最普遍的。

于 2013-10-14T11:14:27.550 回答
-5

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

有关该round()功能的更多信息

于 2012-09-05T09:08:55.103 回答