删除两个小数点后的数字,而不对该值进行舍入

时间:2012-03-30 13:32:42

标签: php function rounding

我在php变量中有价值

$var='2.500000550';
echo $var

我想要的是删除2位数后的所有小数点。

就像现在变量的值将是

$var='2.50';
echo $var
  

请记住这个值来自mysql数据库

但是当我使用round php function时我得到了回合但我不需要回合,我只需要删除2位小数后的所有数字。

我累了,flot()还有很多其他选择没有成功。

由于

15 个答案:

答案 0 :(得分:96)

TL; DR:

PHP本机函数bcdiv似乎完全符合要求,并且正确。

简单地“截断”一个数字bcdiv($var, 1, 2);,其中2是要保留的小数位数(1是指数符 - 将数字除以1可以简单地将原始数字截断为所需的小数位数)

完整答案(历史记录)

事实证明这比人们想象的更难以捉摸。

在这个答案被(错误地)提升了很多之后,我注意到即使是sprintf也会圆了。

我没有删除这个答案,而是将其转化为对每个建议解决方案的更强大的解释/讨论。

number_format - 不正确。 (发)
尝试使用number format

$var = number_format($var, 2, '.', '');  // Last two parameters are optional
echo $var;
// Outputs 2.50

如果你想要它是一个数字,那么只需输入一个浮点数:

$var = (float)number_format($var, 2, '.', '');

注意:正如评论中指出的那样,事实上这确实是 round 的数字。

sprintf - 不正确。 (sprintf也是轮次)
如果不是舍入数字很重要,那么根据下面的答案,使用sprintf

$var = sprintf("%01.2f", $var);

地板 - 不太好! (底数为负数)

floor,通过一些数学计算,将接近你想做的事情:

floor(2.56789 * 100) / 100; // 2.56

其中100表示​​您想要的精度。如果你想要三位数,那么:

floor(2.56789 * 1000) / 1000; // 2.567

然而,这有负数的问题。负数仍然四舍五入,而不是截断:

floor(-2.56789 * 100) / 100; // -2.57

“旧”正确答案:利用楼层的功能

因此,完全可靠的解决方案需要一个功能:

function truncate_number( $number, $precision = 2) {
    // Zero causes issues, and no need to truncate
    if ( 0 == (int)$number ) {
        return $number;
    }
    // Are we negative?
    $negative = $number / abs($number);
    // Cast the number to a positive to solve rounding
    $number = abs($number);
    // Calculate precision number for dividing / multiplying
    $precision = pow(10, $precision);
    // Run the math, re-applying the negative value to ensure returns correctly negative / positive
    return floor( $number * $precision ) / $precision * $negative;
}

以上功能的结果:

echo truncate_number(2.56789, 1); // 2.5
echo truncate_number(2.56789);    // 2.56
echo truncate_number(2.56789, 3); // 2.567

echo truncate_number(-2.56789, 1); // -2.5
echo truncate_number(-2.56789);    // -2.56
echo truncate_number(-2.56789, 3); // -2.567

新的正确答案

使用PHP本机函数bcdiv

echo bcdiv(2.56789, 1, 1);  // 2.5
echo bcdiv(2.56789, 1, 2);  // 2.56
echo bcdiv(2.56789, 1, 3);  // 2.567
echo bcdiv(-2.56789, 1, 1); // -2.5
echo bcdiv(-2.56789, 1, 2); // -2.56
echo bcdiv(-2.56789, 1, 3); // -2.567

答案 1 :(得分:9)

floor(2.500000550 * 100) / 100;

这应该可以完成你的任务......

答案 2 :(得分:6)

您正在请求返回"2.50"而不是2.5的函数,因此您不是在谈论算术而是字符串操作即可。然后preg_replace是你的朋友:

$truncatedVar = preg_replace('/\.(\d{2}).*/', '.$1', $var);

// "2.500000050" -> "2.50", "2.509" -> "2.50", "-2.509" -> "2.50", "2.5" -> "2.5"

如果你想用算术做,只需使用:

$truncatedVar = round($var * 100) / 100);

// "2.500000050" -> "2.5", "2.599" -> "2.59", "-2.599" -> "2.59"

答案 3 :(得分:5)

尝试使用number_format

echo number_format('2.50000050', 2); // 2.50

答案 4 :(得分:4)

number_format对数字进行四舍五入

php > echo number_format(128.20512820513, 2)."\n";
128.21

我使用preg_replace来真正剪切字符串

php > echo preg_replace('/(\.\d\d).*/', '$1', 128.20512820513)."\n";
128.20

答案 5 :(得分:3)

使用sprintf

sprintf("%01.2f", $var);

答案 6 :(得分:2)

有人在这里发布了关于

的信息
  

楼层(2.500000550 * 100)/ 100;

function cutAfterDot($number, $afterDot = 2){
$a = $number * pow(10, $afterDot);
$b = floor($a);
$c = pow(10, $afterDot);
echo "a $a, b $b, c $c<br/>";
return $b/$c ;
}
echo cutAfterDot(2.05,2);

a 205, b 204, c 100
2.04

所以原始形式不要使用它... 但是,如果你添加一点epsilon ......

function cutAfterDot($number, $afterDot = 2){
        return floor($number * pow(10, $afterDot) + 0.00001) / pow(10, $afterDot);
    }

它有效!

答案 7 :(得分:2)

使用PHP本机函数bcdiv

示例:

echo bcdiv(3.22871, 1, 1);  // 3.2
echo bcdiv(3.22871, 1, 2);  // 3.22
echo bcdiv(3.22871, 1, 3);  // 3.228
echo bcdiv(-3.22871, 1, 1); // -3.2
echo bcdiv(-3.22871, 1, 2); // -3.22

对于你的情况:

$var='2.500000550';
echo $var
echo bcdiv($var, 1, 2);  // 2.50

答案 8 :(得分:0)

所有使用number_format的解决方案都是错误的,因为number_format执行舍入。

以下功能适用于所有数字,您可以为使用','的国家/地区指定小数点分隔符。

function truncate_decimal($number, $truncate_decimal_length = 2, $decimal_character = '.', $thousands_character = '') {

$number = explode($decimal_character, $number);
$number[1] = substr($number[1], 0, $truncate_decimal_length);
$number_truncated = implode($decimal_character, $number);
return number_format($number_truncated, $truncate_decimal_length, $decimal_character, $thousands_character);

}

答案 9 :(得分:0)

以下是(我相信 - 请纠正我,如果没有)一个强大的数学 *解决方案,主要基于来自其他几位回答者的信息,以及我的一小部分

(*这并不是说Liphtier's regex-based answer有什么问题 - 只是我可以看到纯粹主义者想要避免正则表达式,这可能是一个数学问题。)

  • sprintf()number_format()(以及round(),显然)都在执行舍入操作,因此不适合问题中请求的非舍入截断(不是自己的,至少)。
  • 代替开箱即用的功能,看似最优雅的解决方案是Sujit Agarwal's answer
  • 但是由于存储了浮点数的方式,我们需要使用epsilon - 正如David Constantine's answer中所指出的那样(通过使用pow()来获得正确的因子,他也使之前的解决方案更加通用基于指定的精度)。
  • 但是,正如cale_b's answer中指出的那样,使用floor()(或大概是ceil())可能会在不使用abs()的情况下产生负面意外的结果。
  • 我尝试添加的值是:
    • 如果在abs()上使用除法来获得否定因子,我们需要考虑输入为0时的特殊情况。
    • 我们应该动态创建epsilon;静态硬编码的epsilon可能太小或太大,具体取决于所需的精度。我还没有在其他答案中看到这个问题。

我使用的代码是:

public static function truncate_decimal($number, $leavePlaces = 2)
{
    if ($number == 0) return 0;
    $negate = $number / abs($number);
    $shiftFactor = pow(10, $leavePlaces);
    $epsilon = pow(10, -1 * $leavePlaces);
    return floor(abs($number) * $shiftFactor + $epsilon) / $shiftFactor * $negate;
}

答案 10 :(得分:0)

一个简单的函数可以是&#34;如果大于0楼,或者ceil&#34;,使用乘数暂时将其提高到小数点以上:

function trim_num($num_in, $dec_places = 2) {
    $multiplier = pow(10, $dec_places); // 10, 100, 1000, etc
    if ($num_in > 0) {
        $num_out = floor($num_in * $multiplier) / $multiplier;
    } else {
        $num_out = ceil($num_in * $multiplier) / $multiplier;
    }
    return $num_out;
}

答案 11 :(得分:0)

$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; 

答案 12 :(得分:0)

  地板 - 不太好! (底数为负数)

来自 cale_b 的可能解决方案。

static public function rateFloor($rate, $decimals)
{

    $div = "1" . str_repeat("0", $decimals);

    if ($rate > 0) {
        return floor($rate * $div) / $div;
    }

    $return = floor(abs($rate) * $div) / $div;

    return -($return);

}
static public function rateCeil($rate, $decimals)
{

    $div = "1" . str_repeat("0", $decimals);

    if ($rate > 0) {
        return ceil($rate * $div) / $div;
    }

    $return = ceil(abs($rate) * $div) / $div;

    return -($return);

}

  

评分:0.00302471

     

楼层:0.00302400

     

Ceil:0.00302500

否定

  

评分:-0.00302471

     

楼层:-0.00302400

     

Ceil:-0.00302500

答案 13 :(得分:0)

如果您不想四舍五入,但是想删除小数位,可以使用“ substr”方法

var ctrl = new StandardPrintController();

using (PrintDocument doc = new PrintDocument())
    {
        doc.PrintController = ctrl;
        doc.PrinterSettings.PrinterName = "CutePDF Writer";
        doc.PrinterSettings.PrintFileName = fileName;

        doc.PrintPage += (s, e) =>
        {
            pageNo++;
            if (pageNo < frameCount)
            {
                e.HasMorePages = true;
            }
            else
            {
                e.HasMorePages = false;
            }
        };

        doc.Print();
    }

答案 14 :(得分:0)

已经有很多可能的解决方案,我只想添加我提出来解决问题的解决方案。

function truncate_decimals($number, $decimals=2)
{
  $factor = pow(10,$decimals); 
  $val = intval($number*$factor)/$factor;
  return $val;
}


truncate_decimals(199.9349,2);
// 199.93