Php 删除两个小数点后的数字,但不舍入值

Php 删除两个小数点后的数字,但不舍入值,php,function,rounding,Php,Function,Rounding,我在php变量中有这样的值 $var='2.500000550'; echo $var 我想要的是删除2位之后的所有小数点 像现在一样,变量的值将是 $var='2.50'; echo $var 请记住,此值来自mysql数据库 但是当我使用round php函数时我得到了round,但我不需要round,我只需要删除2位小数后的所有数字 我累了,flot()还有很多其他选择都没有成功 谢谢试试: 这将完成您的任务…使用 TL;博士: PHP本机函数似乎能够正确地完成所需的工作 为了简单地“

我在php变量中有这样的值

$var='2.500000550';
echo $var
我想要的是删除2位之后的所有小数点

像现在一样,变量的值将是

$var='2.50';
echo $var
请记住,此值来自mysql数据库

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

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

谢谢

试试:

这将完成您的任务…

使用

TL;博士: PHP本机函数似乎能够正确地完成所需的工作

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

完整答案(历史) 事实证明,这比人们想象的更加难以捉摸

在这个答案被(错误地)高估了一点之后,我注意到即使是sprintf也会被说服

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

数字\u格式-不正确。(轮数)
尝试使用:

如果希望它是一个数字,只需键入cast to a float:

$var = (float)number_format($var, 2, '.', '');
注意:正如评论中所指出的,这实际上是对数字的四舍五入

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

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

,再加上一些数学,将接近你想要的:

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
上述功能的结果:

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本机函数


有人在这里发布了关于

地板(2.500000550*100)/100


它起作用了

number\u格式将数字四舍五入

php > echo number_format(128.20512820513, 2)."\n";
128.21
我用preg_replace来真正切断绳子

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

所有使用数字格式的解决方案都是错误的,因为数字格式执行舍入

下面的函数适用于所有数字,您可以为使用“,”的国家/地区指定十进制分隔符

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

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

(*这并不是说它有什么问题——只是我可以看到纯粹主义者想要避免使用正则表达式,因为这可能是一个数学问题。)

  • sprintf()
    number\u format()
    (和
    round()
    ,显然)都在执行舍入操作,因此不适合问题中请求的非舍入截断(至少不是它们自己)
  • 代替开箱即用的功能,看起来最优雅的解决方案是
  • 但由于浮点数的存储方式,我们需要使用ε-正如中所指出的(他还通过使用
    pow()
    来获得基于指定精度的正确因子,从而使前面的解决方案更加通用)
  • 但是,正如中所指出的,如果不使用
    abs()
    ,任何使用
    floor()
    (或者想必是
    ceil()
    )的方法都可能产生意外的负片结果
  • 我想增加的价值是:
    • 如果在
      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;
}

您请求的函数返回的是
“2.50”
,而不是
2.5
,因此,这里讨论的不是算术,而是字符串操作。然后,
preg\u 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"

一个简单的函数是“如果大于0 floor,else 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;
}

使用PHP本机函数

示例:

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
地板-不太好!(底数为负数)

刻度盘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);

}

肯定的

比率:0.00302471

楼层:0.00302400

Ceil:0.00302500

否定的

费率:-0.00302471

楼层:-0.00302400

Ceil:-0.00302500


如果不想对数字进行四舍五入,但想删除小数点,可以使用“substr”方法


已经有很多可能的解决方案了,我只想添加一个解决我问题的方案

函数截断小数($number,$decimals=2)
{
$factor=pow(10,$decimals);
$val=intval($number*$factor)/$factor;
返回$val;
}
截断小数(199.9349,2);
// 199.93

您尝试过数字格式吗?它没有明确的文档记录,但数字格式是循环的。应该提到的是,数字格式返回的是字符串而不是数字。@MuhammadAtif-是的,这不是本文中的正确答案。正确的答案是
bcdiv
顺便说一句,如果您只需要删除数字,那么bcadd($num\u FLO,0,$prec\u INT)是首选的,因为它比div或mul操作更快)@Bill\u VA-谢谢您的评论。事实上,我的代码是正确的(就像你的一样),我的代码遵循“防御”
$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"
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;
}
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
$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; 
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);

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