我需要将 PHP 中的小数四舍五入到小数点后两位,以便:
49.955
变成……
49.95
我试过number_format,但这只是将值四舍五入为49.96。我不能使用substr,因为数字可能更小(例如 7.950)。到目前为止,我一直无法找到答案。
非常感谢任何帮助。
我需要将 PHP 中的小数四舍五入到小数点后两位,以便:
49.955
变成……
49.95
我试过number_format,但这只是将值四舍五入为49.96。我不能使用substr,因为数字可能更小(例如 7.950)。到目前为止,我一直无法找到答案。
非常感谢任何帮助。
这可以工作:floor($number * 100) / 100
不幸的是,以前的答案(包括接受的答案)都不适用于所有可能的输入。
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));
}
此函数适用于正数和负数,以及所需的任何精度。
这是一个很好的函数,它可以在不使用字符串函数的情况下完成任务:
<?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);
}
将输入乘以 100,将其 floor(),然后将结果除以 100。
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
您可以使用 bcdiv PHP 函数。
bcdiv(49.955, 1, 2)
试试这个round()
功能
像这样:round($num, 2, PHP_ROUND_HALF_DOWN);
对于有需要的人,我使用了一个小技巧来克服数学函数故障,例如 floor 或intval(9.7*100)=969奇怪。
function floor_at_decimals($amount, $precision = 2)
{
$precise = pow(10, $precision);
return floor(($amount * $precise) + 0.1) / $precise;
}
所以添加少量(无论如何都会被搁置)以某种方式解决了这个问题。
function floorToPrecision($val, $precision = 2) {
return floor(round($val * pow(10, $precision), $precision)) / pow(10, $precision);
}
您可以使用:
$num = 49.9555;
echo substr($num, 0, strpos($num, '.') + 3);
使用正则表达式的替代解决方案应该适用于所有正数或负数,整数或小数:
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');
}
基于@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);
sprintf("%1.2f",49.955) //49.95
如果您需要在不四舍五入的情况下截断小数 - 这是不合适的,因为它会在最后 49.95 5之前正常工作,如果数字更多,例如 49.95 7,它将四舍五入到 49.96
在我看来,Lght 的答案是最普遍的。
你试过了round($val,2)
吗?
有关该round()
功能的更多信息