PHP删除小数而不会四舍五入

时间:2012-01-31 11:58:39

标签: php decimal rounding

我想在没有四舍五入的情况下删除小数。例如,如果我有1.505,我想删除最后一个小数,值应该是1.50。 PHP中有这样的功能吗?

13 个答案:

答案 0 :(得分:36)

您需要floor()这样:

$rounded = floor($float*100)/100;

或者你转换为整数:

$rounded = 0.01 * (int)($float*100);

这种方式不会四舍五入。

答案 1 :(得分:12)

$float = 1.505;

echo sprintf("%.2f", $float);

//outputs 1.50

答案 2 :(得分:4)

也许为时已晚,但这是一个很好的方法:

    $getTruncatedValue = function( $value, $precision )
    {
        //Casts provided value
        $value = ( string )$value;

        //Gets pattern matches
        preg_match( "/(-+)?\d+(\.\d{1,".$precision."})?/" , $value, $matches );

        //Returns the full pattern match
        return $matches[0];            
    };

    var_dump
    (
        $getTruncatedValue(1.123,1),   //string(3) "1.1"
        $getTruncatedValue(1.345,2),   //string(4) "1.34"
        $getTruncatedValue(1.678,3),   //string(5) "1.678"
        $getTruncatedValue(1.90123,4)  //string(6) "1.9012"  
    );
  • 这种方法的唯一缺陷可能是需要使用正则表达式(有时可能会带来性能损失)。

注意:很难找到截断小数的本机方法,我认为使用sprintf和其他与字符串相关的函数不可能执行此操作。

答案 3 :(得分:3)

要准确地为+ ve -ve数字执行此操作,您需要使用:
- + ve数字的php floor()函数
- 用于-ve numbers的php ceil()函数

function truncate_float($number, $decimals) {
    $power = pow(10, $decimals); 
    if($number > 0){
        return floor($number * $power) / $power; 
    } else {
        return ceil($number * $power) / $power; 
    }
}

原因是floor()总是将数字 向下 ,而不是零。 即floor()有效地舍入-ve数朝向更大的绝对值
例如floor(1.5) = 1floor(-1.5) = -2

因此,对于multiply by power, remove decimals, divide by power截断方法:
- floor()仅适用于正数
- ceil()仅适用于负数

要对此进行测试,请将以下代码复制到http://phpfiddle.org/lite(或类似)的编辑器中:

<div>Php Truncate Function</div>
<br>
<?php
    function truncate_float($number, $places) {
        $power = pow(10, $places); 
        if($number > 0){
            return floor($number * $power) / $power; 
        } else {
            return ceil($number * $power) / $power; 
        }
    }

    // demo
    $lat = 52.4884;
    $lng = -1.88651;
    $lat_tr = truncate_float($lat, 3);
    $lng_tr = truncate_float($lng, 3);
    echo 'lat = ' . $lat . '<br>';
    echo 'lat truncated = ' . $lat_tr . '<br>';
    echo 'lat = ' . $lng . '<br>';
    echo 'lat truncated = ' . $lng_tr . '<br><br>';

    // demo of floor() on negatives
    echo 'floor (1.5) = ' . floor(1.5) . '<br>';
    echo 'floor (-1.5) = ' . floor(-1.5) . '<br>';
?>

答案 4 :(得分:2)

您可以将1.505转换为String数据类型,并使用substring()截断最后一个字符。
再次将其转换为integer

答案 5 :(得分:2)

$num = 118.74999669307;
$cut = substr($num, 0, ((strpos($num, '.')+1)+2));`
// Cut the string from first character to a length of 2 past the decimal.
/ substr(cut what, start, ( (find position of decimal)+decimal itself)+spaces after decimal) )
echo $cut; 

这将有助于缩短浮动值而不会使其四舍五入。

答案 6 :(得分:2)

使用PHP本机函数bcdiv

echo bcdiv(2.56789, 1, 2);  // 2.56

答案 7 :(得分:1)

RenaPot IsisCode goredwards 的答案不正确。

由于浮动在计算机中的工作方式(通常),浮动不准确。

要复制此问题:

floor(19.99 * 100);  // Outputs 1998 instead of 1999
floor( 5.10 * 100);  // Outputs  509 instead of  510

在PHP内部,19.99 * 100会产生类似1998.999999999999999的内容,当我们执行floor时,我们会得到1998

<强>解决方案:

解决方案1 ​​:如果安装了 bcmath 库(由@SamyMassoud建议)(某些共享托管服务器默认情况下可能没有安装它)。像这样:

//floor(19.99 * 100);// Original
floor(bcmul(19.99, 100));// Outputs 1999

解决方案2:字符串操作(我的推荐):

// Works with positive and negative numbers, and integers and floats and strings
function withoutRounding($number, $total_decimals) {
    $number = (string)$number;
    if($number === '') {
        $number = '0';
    }
    if(strpos($number, '.') === false) {
        $number .= '.';
    }
    $number_arr = explode('.', $number);

    $decimals = substr($number_arr[1], 0, $total_decimals);
    if($decimals === false) {
        $decimals = '0';
    }

    $return = '';
    if($total_decimals == 0) {
        $return = $number_arr[0];
    } else {
        if(strlen($decimals) < $total_decimals) {
            $decimals = str_pad($decimals, $total_decimals, '0', STR_PAD_RIGHT);
        }
        $return = $number_arr[0] . '.' . $decimals;
    }
    return $return;
}

// How to use:
withoutRounding(19.99, 2);// Return "19.99"
withoutRounding(1.505, 2);// Return "1.50"
withoutRounding(5.1, 2);// Return "5.10"

答案 8 :(得分:0)

只需(int) $number;即可获得整数

答案 9 :(得分:0)

我知道这是一个迟到的答案,但这是一个简单的解决方案。使用1.505的OP示例,您只需使用以下内容即可达到1.50。

function truncateExtraDecimals($val, $precision) {
    $pow = pow(10, $precision);
    $precise = (int)($val * $pow);
    return (float)($precise / $pow); 
}

这可以管理正值和负值,而无需过滤使用哪个函数,并且可以在不担心其他函数可能对值执行的情况下更正结果。

$val = 1.509;
$truncated = sprintf('%.2f', truncateExtraDecimals($val, 2));
echo "Result: {$truncated}";

Result: 1.50

需要sprintf来获得正好2个小数才能显示,否则结果将是1.5而不是1.50。

答案 10 :(得分:0)

我们可以使用bc函数:

echo bcadd(sprintf('%F', 5.445), '0', 2); // => 5.44
echo sprintf('%.2F', 5.445); // => 5.45

答案 11 :(得分:0)

为避免使用天花板,地板和圆形,只需将其视为绳子并在必要时将其切割即可。这样可以避免所有舍入问题。

下面的代码查找点后的前两个数字并将其选中。然后,它会寻找任何跟在其后的数字。然后,仅用找到的2个数字替换整个内容。如果数字与替换规则不匹配,则没有任何变化。

您可以将其保留在函数调用中,然后将要保留的小数点后的数字和数量传递给函数。

    // Shorten number to 2 decimal places without rounding
    $num = 2213.145;
    $num = floatval(preg_replace("/\.([0-9]{2})[0-9]{0,99}/",".$1",$num));

答案 12 :(得分:0)

简单又好用。

$value = 12.9987876;
$value_exp = explode(".", $value);
$value_new = floatval($value_exp[0].'.'.substr($value_exp[1],0,4));

echo $value_new; // output will 12.9987