删除小数点后两位的数字,不舍入值


Delete digits after two decimal points, without rounding the value

我在php变量中有这样的值

$var='2.500000550';
echo $var

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

就像现在变量的值将是

$var='2.50';
echo $var

请记住,此值来自 MySQL DataBSE

但是当我使用 round php function 我得到了圆形,但我不需要圆形,我只需要删除 2 个小数点后的所有数字。

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

谢谢

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:

$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
floor(2.500000550 * 100) / 100;

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

您请求的函数返回"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"

尝试使用number_format:

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

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

使用 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

有人在这里发布关于

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

它有效!

使用 sprintf

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

以下是(我相信的是 - 如果不是,请纠正我(一个强大的数学*解决方案,主要基于这里其他几个回答者的信息,以及我的少量信息。

(*这并不是说 Liphtier 基于正则表达式的答案有什么问题 - 只是我可以看到纯粹主义者想要避免正则表达式,因为可以说是一个数学问题。

  • sprintf()number_format()(显然还有round()(都在执行舍入操作,因此不适合问题中请求的非舍入截断(至少不是单独(。
  • 代替开箱即用的功能,看似最优雅的解决方案是Sujit Agarwal的答案。
  • 但是由于浮点数的存储方式,我们需要使用 epsilon - 正如 David Constantine 的回答中所指出的那样(他还通过使用 pow() 根据指定的精度获得正确的因子,使前面的解决方案更加通用(。
  • 但是,正如cale_b的回答所指出的那样,任何使用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;
}

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

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

truncate_decimals(199.9349,2);
// 199.93
所有

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

一个简单的函数是"如果大于 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;
}
$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; 

地板 - 不完全是!(地板四舍五入负数(

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

如果您不想对数字进行四舍五入,但要删除小数位,则可以使用"substr"方法

substr(string, start, length);
substr(4.96, 0, -1);