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

PHP如何舍入到小数点后两位?,php,decimal,rounding,number-formatting,Php,Decimal,Rounding,Number Formatting,我需要将PHP中的一个小数点舍入为两位小数,以便: 49.955 变成 49.95 我尝试了number\u格式,但这只是将值舍入到49.96。我无法使用substr,因为该数字可能更小(如7.950)。到目前为止,我还没有找到这个问题的答案 非常感谢您的帮助。您是否尝试了轮($val,2) 有关函数的详细信息使用格式化输出 sprintf("%1.2f",49.955) //49.95 您可以使用: $num = 49.9555; echo substr($num, 0, strpos(

我需要将PHP中的一个小数点舍入为两位小数,以便:

49.955
变成

49.95
我尝试了number\u格式,但这只是将值舍入到49.96。我无法使用substr,因为该数字可能更小(如7.950)。到目前为止,我还没有找到这个问题的答案

非常感谢您的帮助。

您是否尝试了
轮($val,2)


有关函数的详细信息

使用格式化输出

sprintf("%1.2f",49.955) //49.95
您可以使用:

$num = 49.9555;
echo substr($num, 0, strpos($num, '.') + 3);
试试这个函数


如下:
round($num,2,PHP\u round\u HALF\u DOWN)

这是一个很好的函数,它不使用字符串函数就完成了这一任务:

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

将输入乘以100,然后将结果除以100

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

sprintf("%1.2f",49.955) //49.95
如果您需要在不舍入的情况下截断小数-这是不合适的,因为它将正确工作到最后49.955,如果数字更大,例如49.957,它将舍入到49.96

在我看来,Lght关于发言权的答案是最普遍的。

不幸的是,之前的答案(包括公认的答案)都不适用于所有可能的输入

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));
}
函数floorDec($val,$precision=2){
如果($precision<0){$precision=0;}
$numPointPosition=intval(strpos($val,'.');
如果($numPointPosition==0){/$val是一个整数
返回$val;
}
返回floatval(substr($val,0,$numPointPosition+$precision+1));
}
此函数适用于正数和负数以及所需的任何精度

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
此函数以任意精度处理正小数和负小数


这里的代码示例:

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

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

我认为有一个非常简单的方法来实现这一点:

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

这是一本书。您需要安装BCMath,但我认为它通常与PHP安装捆绑在一起

您可以使用bcdiv PHP函数

bcdiv(49.955, 1, 2)

基于@huysentruitw和@alexanswer,我提出了以下函数来实现这个技巧

它通过了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
}

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

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

因此,添加少量(无论如何都会被忽略)可以解决这个问题。

它仍然返回49.96,他想要的是49.95尝试使用“mode”参数。一个是PHP_ROUND_HALF_UP,PHP_ROUND_HALF_DOWN,PHP_ROUND_HALF_偶数,或PHP_ROUND_HALF_ODD。否则,你可以使用蛮力法:floor(100*$val)/100。但轮不是他需要的。OP说他不想再轮了。Round()以.5或更大的整数取整。Round($num,2,PHP_Round_HALF_DOWN);?是的,我忘了。但是你在最初的回答中没有提到:)(顺便说一句,我并不是投你反对票的那个人)@user1606963 PHP_ROUND_HALF_DOWN只会精确地确定小数点的一半会发生什么……它不会模拟在小数点的一半或更大的地方舍入的楼层。例如
round(1.115,2,PHP\u round\u HALF\u DOWN)
将四舍五入到1.11,但是
四舍五入(1.116,2,PHP\u四舍五入到一半)仍将四舍五入到1.12,这不是期望的结果。关于乘以100、加地板和除以100的答案是我所知道的唯一一种实现舍入到2位小数的方法,同时总是向下舍入。(当然,除非转换为字符串并以这种方式进行操作)floor(50.5)=50=>50/100=0.50工作不可靠,但不是因为floor函数,而是奇怪的PHP数学<代码>9.7*100;//浮点970
(int)(9.7*100);//int 969
不是奇怪的PHP数学,而是大多数编程语言中都存在的浮点数精度问题($number/100)*100,与本例不同请注意,这不适用于负数。它将“-0.57471264367815”转换为“-1.42528”您的代码不工作:
$x=1000.000000019;echo汇总(x,8美元)输出1000。90000264@maxpovver谢谢,修好了function@SvenKahnThx,函数现在与负数一起工作。嘿,我知道这是很久以前的事了,但是如果
$val
是科学符号中的浮点数,比如
-3E-15
@zedling确实,
floorDev
期望一个“经典”符号,那么即使你的解决方案也会失败。我想你可以在
$val
中检查'e'中的'e',然后转换成字符串符号。请给你的代码添加一些解释-已经有多个其他答案,你应该解释是什么让你的答案比其他答案更好,或者甚至是差分。即使使用floorp(2.05,2)这样的数字,减法也能起作用(第一个函数没有)。要正确处理负数,必须使用第三轮()参数:round($val-$half,$precision,$val
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
}
// round afterwards to cast 0.00 to 0
// set $divider to 1 when no division is required
round(bcdiv($number, $divider, $decimalPlaces), $decimalPlaces);
function floor_at_decimals($amount, $precision = 2)
{
    $precise = pow(10, $precision);
    return floor(($amount * $precise) + 0.1) / $precise;
}