简体   繁体   English

PHP 如何四舍五入到小数点后两位?

[英]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)

Try the round() function试试round()函数

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

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.所以添加少量(无论如何都会被淘汰)以某种方式解决了这个问题。

Use formatted output使用格式化输出

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

DEMO演示

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 的回答是最普遍的。

What about this? 那这个呢?

$value = 49.955;

echo intval( $value * 100 ) / 100;

Here is a demo 这是一个演示

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

More information about the round() function有关round()函数的更多信息

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM