繁体   English   中英

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

[英]Remove useless zero digits from decimals in PHP

我试图找到一种快速的方法来从这样的数值中删除zero decimals

echo cleanNumber('125.00');
// 125

echo cleanNumber('966.70');
// 966.7

echo cleanNumber(844.011);
// 844.011

是否存在一些优化的方法来做到这一点?

$num + 0可以解决问题。

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

在内部,这相当于使用(float)$numfloatval($num)强制转换为浮动,但我发现它更简单。

你可以只使用floatval函数

echo floatval('125.00');
// 125

echo floatval('966.70');
// 966.7

echo floatval('844.011');
// 844.011

这就是我使用的:

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

注意这是假设. 是小数点分隔符。 它的优点是它可以处理任意大(或小)的数字,因为没有浮点数。 它也不会将数字转换为科学记数法(例如 1.0E-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)

对于来到此站点的每个人都遇到与逗号相同的问题,请更改:

$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 数字:小数点仅在需要时可见

如果要删除之前的零位以显示在页面或模板上。

您可以使用sprintf()函数

sprintf('%g','125.00');
//125

‌‌sprintf('%g','966.70');
//966.7

‌‌‌‌sprintf('%g',844.011);
//844.011

您应该将您的数字转换为浮点数,这将为您执行此操作。

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

这将是您正在寻找的输出。

42.422005

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

没有什么是不能用简单的正则表达式解决的;)

http://xkcd.com/208/

类型转换为float

$int = 4.324000;
$int = (float) $int;

小心添加+0。

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

结果是1。

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

echo floatval('1000.00');
//1000

由于这个问题是旧的。 首先,我对此感到抱歉。

问题是关于数字 xxx.xx 但如果它是 x,xxx.xxxxxx 或差异小数分隔符,例如 xxxx,xxxx,这可能更难找到并从十进制值中删除零位。

/**
 * Remove zero digits (include zero trails - 123.450, 123.000) 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. Only return as string!
 */
function removeZeroDigitsFromDecimal($number, $decimal_sep = '.')
{
    $explode_num = explode($decimal_sep, $number);
    if (is_countable($explode_num) && count($explode_num) > 1) {
        // if exploded number is more than 1 (Example: explode with . for nnnn.nnn is 2)
        // replace `is_countable()` with `is_array()` if you are using PHP older than 7.3.
        $explode_num[count($explode_num)-1] = preg_replace('/(0+)$/', '', $explode_num[count($explode_num)-1]);
        if ($explode_num[count($explode_num)-1] === '') {
            // if the decimal value is now empty. 
            // unset it to prevent nnn. without any number.
            unset($explode_num[count($explode_num)-1]);
        }
        $number = implode($decimal_sep, $explode_num);
    }
    unset($explode_num);
    return (string) $number;
}

这是测试代码。

$tests = [
    1234 => 1234,
    -1234 => -1234,
    '12,345.67890' => '12,345.6789',
    '-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 ($tests as $number => $assert) {
    $result = removeZeroDigitsFromDecimal($number);
    assert($result === (string) $assert, new \Exception($result . ' (' . gettype($result) . ') is not matched ' . $assert . ' (' . gettype($assert) . ')'));
    echo $number . ' =&gt; ' . (string) $assert . '<br>';
}

echo '<hr>' . PHP_EOL;

$tests = [
    1234 => 1234,
    -1234 => -1234,
    '12.345,67890' => '12.345,6789',
    '-12.345.678,901234' => '-12.345.678,901234',
    '12345,000000' => '12345',
    '-12345,000000' => '-12345',
    '-12.345,000000000' => '-12.345',
    '-12.345,000000,000' => '-12.345,000000',// this is correct assertion. Weird ,000000,000 but only last 000 will be removed.
];
foreach ($tests as $number => $assert) {
    $result = removeZeroDigitsFromDecimal($number, ',');
    assert($result === (string) $assert, new \Exception($result . ' (' . gettype($result) . ') is not matched ' . $assert . ' (' . gettype($assert) . ')'));
    echo $number . ' =&gt; ' . (string) $assert . '<br>';
}

所有测试都应该通过并且没有错误。

为什么'-12.345,000000,000'将是'-12.345,000000'而不是'-12.345'
因为此功能用于从十进制值中删除零位(包括零尾迹)。 这不是对正确数字格式的验证。 那应该是另一个功能。

为什么总是以字符串形式返回?
因为在计算中最好用bcxxx函数,或者用大数。

奇怪的是,当我从数据库中得到一个“浮点数”类型的数字并且我的数字是 ex 时。 10000 当我对其进行浮点运算时,它变为 1。

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

我已经测试了上述所有解决方案,但没有奏效。

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

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

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, ',', '.');
}

下面就简单多了

if(floor($num) == $num) {
    echo number_format($num);
} else {
    echo $num;
}

您可以尝试以下方法:

rtrim(number_format($coin->current_price,6),'0.')

示例 1

$value =81,500.00;
{{rtrim(rtrim(number_format($value,2),0),'.')}}

输出

81,500

示例 2

$value=110,763.14;
{{rtrim(rtrim(number_format($value,2),0),'.')}}

输出

110,763.14

复杂的方式但有效:

$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

那是我的小解决方案......可以包含在一个类中并设置变量

私人 $dsepparator = '.'; // 小数 private $tsepparator= ','; // 千

这可以由构造函数设置并更改为用户语言。

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
     */

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

您可以使用:

print (floatval)(number_format( $Value), 2 ) );    

这是我的解决方案。 我想保留添加千位分隔符的能力

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

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

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

简单准确!

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

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

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

它适用于任何情况

我使用这个简单的代码:

define('DECIMAL_SEPARATOR', ','); //To prove that it works with different separators than "."

$input = "50,00";

$number = rtrim($input, '0');                // 50,00 --> 50,
$number = rtrim($number, DECIMAL_SEPARATOR); // 50,   --> 50

echo $number;

似乎有点太容易成为真正正确的解决方案,但它对我来说效果很好。 在使用它之前,您应该对将获得的输入进行一些测试。

有时,特别是在货币金额的情况下,您只想在它们为 2 时删除零,您不想打印€ 2.1而不是€ 2.10

一些实现可能是:

function formatAmount(string|float|int $value, int $decimals = 2): string
{
    if (floatval(intval($value)) === floatval($value)) {
        // The number is an integer. Remove all the decimals
        return rtrim($value, '0.');
    }

    return number_format($value, $decimals);
}

或者,如果$decimals始终为 2,则更简单:

function formatAmount(string|float|int $value): string
{
    return str_replace('.00', '', number_format($value, 2));
}

预期输出示例:

0.1000 => 0.10
2.000 => 2
1.25 => 1.25

假设金额是一个带 2 位小数的字符串,那么您可以使用:

protected function removeZerosDecimals(string $money): string
{
    $formatter = new NumberFormatter('en_US', NumberFormatter::CURRENCY);

    $uselessDecimals = sprintf(
        '%s00',
        $formatter->getSymbol(NumberFormatter::DECIMAL_SEPARATOR_SYMBOL)
    );
    if (!str_ends_with($money, $uselessDecimals)) {
        return $money;
    }

    $len = mb_strlen($money);
    return mb_substr($money, 0, $len - mb_strlen($uselessDecimals));
}

这将按预期工作?任何? 货币,例如$500.00R$ 500,00

function removeZerosAfterDecimals($number) {

$number = trim($number);

if($number <= 0 || empty($number)) {
    return $number;
}

$ary = explode('.', $number);

if(count($ary) <= 1) {
    return $number;
}

$reverseAry = array_reverse($ary);

$endSearch = false;
$newNumber = [];

for($i=0; $i<count($reverseAry); $i++) {
    if($reverseAry[$i] != 0 && $endSearch === false) {
        $newNumber[] = $reverseAry[$i];
        $endSearch = true;
    } else if ($endSearch === true) {
        $newNumber[] = $reverseAry[$i];
    }
}


return implode('.',array_reverse($newNumber));

}

//输出:10.0.1.0 => 10.0.1

//输出:10.0.1 => 10.0.1

//输出:10.1.2 => 10.1.2

//输出:10.0.0 => 10

此函数只会删除尾随的零小数

此代码将删除点后的零,并且仅返回两位小数。

$数字=1200.0000;
str_replace('.00', '',number_format($number, 2, '.', ''));

输出为:1200

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM