在PHP中从小数中删除无用的零数字


163

我正在尝试找到一种zero decimals从数字值中删除的快速方法,如下所示:

echo cleanNumber('125.00');
// 125

echo cleanNumber('966.70');
// 966.7

echo cleanNumber(844.011);
// 844.011

是否存在某种优化的方法?


4
由于您的值实际上是字符串,所以为什么不直接使用rtrim()- php.net/manual/en/function.rtrim.php-带有'0'。作为第二个论点
马克·贝克

抱歉,我不太清楚,它们并不总是字符串,我解决了这个问题。
vitto

9
@Mark Ba​​ker:这是一个不好的方法,因为数字120将被裁剪为12
machineaddict

@machineaddict-且仅当字符串值不带小数点时才会..... OP引用的所有字符串都带小数点。
马克贝克2014年

2
然后,您应该在答案中添加一个大胆的提示,即只有在有小数的情况下它才起作用。
machineaddict

Answers:


353

$num + 0 绝招。

echo 125.00 + 0; // 125
echo '125.00' + 0; // 125
echo 966.70 + 0; // 966.7

在内部,这等效于使用(float)$num或进行浮点转换,floatval($num)但我发现它更简单。


45
我认为这是一个肮脏的把戏。我不喜欢它,因为代码没有像floatval()这样做那样说明他的行为。
ESCOBAR 2014年

4
@ESCOBAR floatval的行为返回一个浮点数。我认为使用它作为小数点格式器不是很明显,也不是干净的。
lafor

2
这是非常不清楚的。我们的团队刚刚在我们的代码中遇到了这个问题,并且有3位开发人员困惑了一段时间。我认为马克的答案是更好的选择。它更长,但目的很明确。
jfbalanc 2015年

2
@jfbalanc//COMMENT
Webinan 2015年

1
@ESCOBAR不是,这是一种正式建议的类型转换方法...在php.net上搜索“类型变戏法”
Gergely Lukacsy

101

你可以只使用floatval功能

echo floatval('125.00');
// 125

echo floatval('966.70');
// 966.7

echo floatval('844.011');
// 844.011

2
当千位分隔符是点并且小数点是逗号时,它将失败。
Munna Khan,

20

这是我用的:

function TrimTrailingZeroes($nbr) {
    return strpos($nbr,'.')!==false ? rtrim(rtrim($nbr,'0'),'.') : $nbr;
}

注意:这.是十进制分隔符。它的优点是,由于没有浮点强制转换,因此可以处理任意大(或小)数字。它还不会将数字转换为科学计数法(例如1.0E-17)。


这不是一个安全的解决方案,如果价格不是小数怎么办?例如,如果开发人员将价格乘以整数,那么我们得到一个整数
amin

@alex此函数适用于整数,浮点数和字符串。
mpen

1
完美的解决方案,作为bcmath的助手
Kart Av1k

17

简单地添加+到您的字符串变量将导致类型转换为(float)并删除零:

var_dump(+'125.00');     // double(125)
var_dump(+'966.70');     // double(966.7)
var_dump(+'844.011');    // double(844.011)
var_dump(+'844.011asdf');// double(844.011)

13

对于所有来此网站的人,如果他们在逗号上都遇到相同的问题,请更改:

$num = number_format($value, 1, ',', '');

至:

$num = str_replace(',0', '', number_format($value, 1, ',', '')); // e.g. 100,0 becomes 100


如果要删除两个零,则更改为:

$num = str_replace(',00', '', number_format($value, 2, ',', '')); // e.g. 100,00 becomes 100

此处更多信息:PHP数字:仅在需要时可见小数点



9

您应该将数字转换为浮点数,这将为您做到这一点。

$string = "42.422005000000000000000000000000";
echo (float)$string;

此输出将是您想要的。

42.422005


1
浮动铸造也可能会破坏您的电话号码。例如(float)'0.1234567890124567890123456789'成为0.12345678901246
mpen

8
$x = '100.10'; 
$x = preg_replace("/\.?0*$/",'',$x); 
echo $x;

没有简单的正则表达式无法解决的问题;)

http://xkcd.com/208/


1
去除有效0的,例如in "100"。也没有剥离0小号关闭"100.010"
mpen

2
大家退后!$x = preg_replace("/(\.0*$)|((?<=\.\d*)0+$)/",'',$x);
伊曼纽尔·S,


2

由于这个问题太老了。首先,对此我感到抱歉。

问题是关于数字xxx.xx的问题,但是如果它是x,xxx.xxxxx或不同的十进制分隔符(例如xxxx,xxxx),则可能很难找到并从十进制值中删除零位。

/**
 * Remove zero digits from decimal value.
 * 
 * @param string|int|float $number The number can be any format, any where use in the world such as 123, 1,234.56, 1234.56789, 12.345,67, -98,765.43
 * @param string The decimal separator. You have to set this parameter to exactly what it is. For example: in Europe it is mostly use "," instead of ".".
 * @return string Return removed zero digits from decimal value.
 */
function removeZeroDigitsFromDecimal($number, $decimal_sep = '.')
{
    $explode_num = explode($decimal_sep, $number);
    if (is_array($explode_num) && isset($explode_num[count($explode_num)-1]) && intval($explode_num[count($explode_num)-1]) === 0) {
        unset($explode_num[count($explode_num)-1]);
        $number = implode($decimal_sep, $explode_num);
    }
    unset($explode_num);
    return (string) $number;
}

这是测试代码。

$numbers = [
    1234,// 1234
    -1234,// -1234
    '12,345.67890',// 12,345.67890
    '-12,345,678.901234',// -12,345,678.901234
    '12345.000000',// 12345
    '-12345.000000',// -12345
    '12,345.000000',// 12,345
    '-12,345.000000000',// -12,345
];
foreach ($numbers as $number) {
    var_dump(removeZeroDigitsFromDecimal($number));
}


echo '<hr>'."\n\n\n";


$numbers = [
    1234,// 12324
    -1234,// -1234
    '12.345,67890',// 12.345,67890
    '-12.345.678,901234',// -12.345.678,901234
    '12345,000000',// 12345
    '-12345,000000',// -12345
    '12.345,000000',// 12.345
    '-12.345,000000000',// -12.345
    '-12.345,000000,000',// -12.345,000000 STRANGE!! but also work.
];
foreach ($numbers as $number) {
    var_dump(removeZeroDigitsFromDecimal($number, ','));
}

2

加+0时要小心。

echo number_format(1500.00, 2,".",",")+0;
//1

结果是1。

echo floatval('1,000.00');
// 1

echo floatval('1000.00');
//1000

您正在回答一个2013
。– VTodorov '18

3
如果它可以帮助实际的读者,那么回答一个老问题就不是问题了
Reign.85 '18

1

奇怪,当我从数据库中获取一个带有“ float”类型的号码并且我的号码是ex时。浮动时为10000,则变为1。

$number = $ad['price_month']; // 1000 from the database with a float type
echo floatval($number);
Result : 1

我已经测试了上面所有的解决方案,但是没有用。


1
$str = 15.00;
$str2 = 14.70;
echo rtrim(rtrim(strval($str), "0"), "."); //15
echo rtrim(rtrim(strval($str2), "0"), "."); //14.7

0

方式复杂但有效:

$num = '125.0100';
$index = $num[strlen($num)-1];
$i = strlen($num)-1;
while($index == '0') {
   if ($num[$i] == '0') {
     $num[$i] = '';
     $i--;
   }

   $index = $num[$i];
}

//remove dot if no numbers exist after dot
$explode = explode('.', $num);
if (isset($explode[1]) && intval($explode[1]) <= 0) {
   $num = intval($explode[0]);
}

echo $num; //125.01

上面的解决方案是最佳方法,但是如果您想拥有自己的解决方案,则可以使用此方法。该算法的作用是从字符串的末尾开始,并检查其是否为0,如果设置为空字符串,则从后退到下一个字符,直到最后一个字符> 0



0

多数民众赞成在我的小解决方案...可以包含到一个类,并设置vars

private $ dsepparator ='。'; //十进制小数$ tsepparator =','; //一千

可以由构造函数设置,然后更改为用户lang。

class foo
{
    private $dsepparator;
    private $tsepparator;

    function __construct(){
        $langDatas = ['en' => ['dsepparator' => '.', 'tsepparator' => ','], 'de' => ['dsepparator' => ',', 'tsepparator' => '.']];
        $usersLang = 'de'; // set iso code of lang from user
        $this->dsepparator = $langDatas[$usersLang]['dsepparator'];
        $this->tsepparator = $langDatas[$usersLang]['tsepparator'];
    }

    public function numberOmat($amount, $decimals = 2, $hideByZero = false)
    {
        return ( $hideByZero === true AND ($amount-floor($amount)) <= 0 ) ? number_format($amount, 0, $this->dsepparator, $this->tsepparator) : number_format($amount, $decimals, $this->dsepparator, $this->tsepparator);
    }
    /*
     * $bar = new foo();
     * $bar->numberOmat('5.1234', 2, true); // returns: 5,12
     * $bar->numberOmat('5', 2); // returns: 5,00
     * $bar->numberOmat('5.00', 2, true); // returns: 5
     */

}

所以我建立了一个样本很少的样本类。更好?=)
Paykoman

0

这是我的解决方案。我想保持添加数千个分隔符的能力

    $precision = 5;    
    $number = round($number, $precision);
    $decimals = strlen(substr(strrchr($number, '.'), 1));
    return number_format($number, $precision, '.', ',');

0

这是一个使用rtrim,保存分隔符和小数点的简单单行函数:

function myFormat($num,$dec)
 {
 return rtrim(rtrim(number_format($num,$dec),'0'),'.');
 }

0

我发现此解决方案是最好的:

public function priceFormat(float $price): string
{
    //https://stackoverflow.com/a/14531760/5884988
    $price = $price + 0;
    $split = explode('.', $price);
    return number_format($price, isset($split[1]) ? strlen($split[1]) : 2, ',', '.');
}

0

简单准确!

function cleanNumber($num){
    $explode = explode('.', $num);
    $count   = strlen(rtrim($explode[1],'0'));
    return bcmul("$num",'1', $count);
}

0

最终解决方案:唯一安全的方法是使用正则表达式:

echo preg_replace("/\.?0+$/", "", 3.0); // 3
echo preg_replace("/\d+\.?\d*(\.?0+)/", "", 3.0); // 3

在任何情况下都可以使用



-1
$value = preg_replace('~\.0+$~','',$value);

1
如果您对代码的功能以及如何解决原始问题进行了说明,则可以提高答案的质量。
奈杰尔·

@Nikhil Gyan我同意这个答案不是很好。随时注意。但是,我至少认为对于质量很低的标志来说还不够糟糕
Sam Hartman

-2

该代码将在点后删除零,并且将仅返回两位十进制数字。

$ number = 1200.0000;
str_replace('。00','',number_format($ number,2,'。',``)));

输出将是:1200

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.