[英]PHP How do I round down to two decimal places?
I need to round down a decimal in PHP to two decimal places so that:我需要将 PHP 中的小数四舍五入到两位小数,以便:
49.955
becomes...变成……
49.95
I have tried number_format , but this just rounds the value to 49.96 .我试过number_format ,但这只是将值四舍五入到49.96 。 I cannot use substr because the number may be smaller (such as 7.950).我不能使用substr,因为数字可能更小(例如 7.950)。 I've been unable to find an answer to this so far.到目前为止,我一直无法找到答案。
Any help much appreciated.非常感谢任何帮助。
这可以工作: floor($number * 100) / 100
Unfortunately, none of the previous answers (including the accepted one) works for all possible inputs.不幸的是,之前的答案(包括接受的答案)都不适用于所有可能的输入。
1) sprintf('%1.'.$precision.'f', $val)
1) sprintf('%1.'.$precision.'f', $val)
Fails with a precision of 2 : 14.239 should return 14.23 (but in this case returns 14.24).精度为 2 时失败:14.239 应返回 14.23(但在这种情况下返回 14.24)。
2) floatval(substr($val, 0, strpos($val, '.') + $precision + 1))
2) floatval(substr($val, 0, strpos($val, '.') + $precision + 1))
Fails with a precision of 0 : 14 should return 14 (but in this case returns 1)精度为 0 时失败:14 应返回 14(但在这种情况下返回 1)
3) substr($val, 0, strrpos($val, '.', 0) + (1 + $precision))
3) substr($val, 0, strrpos($val, '.', 0) + (1 + $precision))
Fails with a precision of 0 : -1 should return -1 (but in this case returns '-')精度为 0 时失败:-1 应返回 -1(但在这种情况下返回 '-')
4) floor($val * pow(10, $precision)) / pow(10, $precision)
4) floor($val * pow(10, $precision)) / pow(10, $precision)
Although I used this one extensively, I recently discovered a flaw in it ;虽然我广泛使用了这个,但我最近发现了它的一个缺陷; it fails for some values too.对于某些值,它也失败了。 With a precision of 2 : 2.05 should return 2.05 (but in this case returns 2.04 !!)精度为 2 : 2.05 应该返回 2.05 (但在这种情况下返回 2.04 !!)
So far the only way to pass all my tests is unfortunately to use string manipulation.不幸的是,到目前为止,通过我所有测试的唯一方法是使用字符串操作。 My solution based on rationalboss one, is :我基于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));
}
This function works with positive and negative numbers, as well as any precision needed.此函数适用于正数和负数,以及所需的任何精度。
Here is a nice function that does the trick without using string functions:这是一个很好的函数,它在不使用字符串函数的情况下完成了这项工作:
<?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);
?>
An other option is to subtract a fraction before rounding:另一种选择是在四舍五入之前减去一个分数:
function floorp($val, $precision)
{
$half = 0.5 / pow(10, $precision); // Can be cached in a lookup table
return round($val - $half, $precision);
}
I think there is quite a simple way to achieve this:我认为有一种非常简单的方法可以实现这一目标:
$rounded = bcdiv($val, 1, $precision);
Here is a working example .这是一个工作示例。 You need BCMath installed but I think it's normally bundled with a PHP installation.您需要安装 BCMath,但我认为它通常与 PHP 安装捆绑在一起。 :) Here is the documentation . :)这是文档。
将您的输入乘以 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
This function works with positive and negative decimals at any precision.此函数适用于任何精度的正小数和负小数。
Code example here: http://codepad.org/1jzXjE5L这里的代码示例: http : //codepad.org/1jzXjE5L
您可以使用 bcdiv PHP 函数。
bcdiv(49.955, 1, 2)
function floorToPrecision($val, $precision = 2) {
return floor(round($val * pow(10, $precision), $precision)) / pow(10, $precision);
}
For anyone in need, I've used a little trick to overcome math functions malfunctioning, like for example floor or intval(9.7*100)=969 weird.对于有需要的任何人,我使用了一个小技巧来克服数学函数故障,例如 floor 或intval(9.7*100)=969奇怪。
function floor_at_decimals($amount, $precision = 2)
{
$precise = pow(10, $precision);
return floor(($amount * $precise) + 0.1) / $precise;
}
So adding little amount (that will be floored anyways) fixes the issue somehow.所以添加少量(无论如何都会被淘汰)以某种方式解决了这个问题。
You can use:您可以使用:
$num = 49.9555;
echo substr($num, 0, strpos($num, '.') + 3);
An alternative solution using regex which should work for all positive or negative numbers, whole or with decimals:使用正则表达式的替代解决方案应该适用于所有正数或负数,整数或小数:
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');
}
Based on @huysentruitw and @Alex answer, I came up with following function that should do the trick.基于@huysentruitw 和@Alex 的回答,我想出了以下应该可以解决问题的函数。
It pass all tests given in Alex's answer (as why this is not possible) and build upon huysentruitw's answer.它通过了 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
}
The key is to add or subtract delta based on original number sign, to support trimming also negative numbers.关键是根据原始数字符号添加或减去 delta,以支持修剪负数。 Last thing is to get rid of negative zeros (-0) as that can be unwanted behaviour.最后一件事是摆脱负零 (-0),因为这可能是不需要的行为。
Link to "test" playground .链接到“测试”游乐场。
EDIT: bcdiv seems to be the way to go.编辑: 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
if you need to truncate decimals without rounding - this is not suitable, because it will work correctly until 49.95 5 at the end, if number is more eg 49.95 7 it will round to 49.96如果您需要在不四舍五入的情况下截断小数 - 这不合适,因为它会在最后 49.95 5之前正常工作,如果数字更多,例如 49.95 7它将四舍五入到 49.96
It seems for me that Lght`s answer with floor is most universal.在我看来,Lght 对 floor 的回答是最普遍的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.