php-删除两位小数点后的数字,而不舍入该值

我在php变量中有这样的价值

$var='2.500000550';
echo $var

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

像现在变量的值将是

$var='2.50';
echo $var

请记住,此值来自mysql数据库

但是,当我使用flot()时,我四舍五入,但是我不需要四舍五入,我只需要删除2位小数后的所有数字即可。

我已经厌倦了flot()和许多其他选择,但没有成功。

谢谢

air asked 2020-08-08T23:35:07Z
14个解决方案
102 votes

TL; DR:

PHP本机函数bcdiv似乎恰好可以正确地执行所需的操作。

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

完整答案(历史记录)

事实证明,这比人们想象的要难得多。

在这个答案被(错误地)提高了很多之后,我注意到甚至sprintf都会四舍五入。

与其删除此答案,不如将其变成对每个提出的解决方案的更可靠的解释/讨论。

number_format-不正确。 (回合)
尝试使用数字格式:

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

如果您希望它是一个数字,则只需将其强制转换为浮点数即可:

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

注意:正如评论中指出的那样,实际上这是对数字的舍入。

sprintf-错误。 (sprintf也四舍五入)
如果不舍入该数字很重要,则根据以下答案,使用sprintf:

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

地板-不完全! (底数为负数)

一些数学知识,就可以轻松完成您想要的工作:

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
random_user_name answered 2020-08-08T23:36:45Z
9 votes
floor(2.500000550 * 100) / 100;

这应该完成您的任务...

Sujit Agarwal answered 2020-08-08T23:37:05Z
6 votes

您所请求的函数返回的是3002989799579059059200而不是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"
flu answered 2020-08-08T23:37:29Z
5 votes

尝试使用number_format:

echo number_format('2.50000050', 2); // 2.50
matino answered 2020-08-08T23:37:49Z
3 votes

使用sprintf

sprintf("%01.2f", $var);
Aurimas Ličkus answered 2020-08-08T23:38:09Z
3 votes

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
Liphtier answered 2020-08-08T23:38:34Z
2 votes

有人在这里发布

地板(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);
    }

有用!

David Constantine answered 2020-08-08T23:39:07Z
2 votes

使用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
Faisal answered 2020-08-08T23:39:35Z
0 votes

所有使用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);

}
leexonline answered 2020-08-08T23:40:00Z
0 votes

以下是(我相信是的-如果没有请纠正我的话)一个可靠的数学*解决方案,主要基于此处其他几个答复者的信息,以及少量的信息

(*这并不表示Liphtier基于正则表达式的答案有什么问题-只是我可以看到纯粹主义者希望避免正则表达式出现数学问题)。

  • abs()ceil()(显然是abs())都在执行舍入运算,因此不适用于问题中要求的非舍入截断(至少不是靠它们自己)。
  • 代替开箱即用的功能,看似最优雅的解决方案是Sujit Agarwal的回答
  • 但是由于浮点数的存储方式,我们需要使用epsilon-正如David Constantine的答案所指出的(他还通过使用abs()通过指定的精度获得了正确的因子,从而使以前的解决方案更加通用)。
  • 但是然后,正如cale_b的答案所指出的,任何使用abs()(或大概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;
}
Sepster answered 2020-08-08T23:41:00Z
0 votes

一个简单的函数是“如果大于0楼,否则ceil”,在执行此操作时使用乘法器将其暂时提高到小数点以上:

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;
}
David Bell answered 2020-08-08T23:41:21Z
0 votes
$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; 
Sujjad Ali answered 2020-08-08T23:41:36Z
0 votes

地板-不完全! (底数为负数)

来自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

细胞:0.00302500

汇率:-0.00302471

地板:-0.00302400

细胞:-0.00302500

Jon C. answered 2020-08-08T23:42:34Z
0 votes

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

substr(string, start, length);
substr(4.96, 0, -1);
Fahad Ahmed answered 2020-08-08T23:42:55Z
translate from https://stackoverflow.com:/questions/9944001/delete-digits-after-two-decimal-points-without-rounding-the-value