简体   繁体   中英

PHP show only significant (non-zero) decimals

In PHP (using built-in functions) I'd like to convert/format a number with decimal, so that only the non-zero decimals show. However, another requirement of mine is that if it's a number without a decimal value, I'd still like to show that zero. Examples:

9.000 -> 9.0
9.100 -> 9.1
9.120 -> 9.12
9.123 -> 9.123

rtrim($value, "0") almost works. The problem with rtrim is that it leaves 9.000 as 9. . sprintf() seemed like a candidate, but I couldn't get it to have a variable amount of decimals. number_format() serves a different purpose, and those were all I could come up with...

Again, I'd like to point out that I am not looking for your homemade solutions to this, I'm looking for a way to accomplish this using internal PHP functionality. I can write a function that will accomplish this easily myself, so hold answers like that.

I don't think theres a way to do that. A regex is probably your best solution:

$value = preg_replace('/(\.[0-9]+?)0*$/', '$1', $value);

Demo:

php> $a = array('0.000', '0.0001', '0.0101', '9.000', '9.100', '9.120', '9.123');
php> foreach($a as $b) { echo $b . ' => ' . preg_replace('/(\.[0-9]+?)0*$/', '$1', $b)."\n"; }
0.000 => 0.0
0.0001 => 0.0001
0.0101 => 0.0101
9.000 => 9.0
9.100 => 9.1
9.120 => 9.12
9.123 => 9.123

try something like this

$number = 2.00;
echo floor_dec($number,$deg);

    function floor_dec($number, $deg = null)
    {
        if ($deg == null)
            return $number * 1000 / 1000;
        else
            return $number * pow(10, $deg) / pow(10, $deg);
    }

will display "2"

Shouldn't it be?:

$value = preg_replace('~0*$~', '', $value);

The PHP preg_replace syntax is

mixed preg_replace ( mixed $pattern , mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] )

If you want a built-in solution and you're using a PHP version later than 4.2 you could try floatval() :

echo floatval(9.200);

prints

9.2

but

echo floatval(9.123);

prints

9.123

Hope this helps.

A trailing zero is significant:

  • A value of 9.0 implies, that the real value is more than 8.9 and less than 9.1
  • A value of 9.00000 implies, that the real value is more than 8.99999 and less than 9.00001

Therefore, your requirement is quite unusual. That's the reason why no function exists to do what you want.

<?php
    $numbers = array(
        "9.000",
        "9.100",
        "9.120",
        "9.123"
    );
    foreach($numbers as $number) {
        echo sprintf(
            "%s -> %s\n",
            $number,
            (float) $number == (int) $number ? number_format($number, 1) : (float) $number
        );
    }
?>

Output:

9.000 -> 9.0
9.100 -> 9.1
9.120 -> 9.12
9.123 -> 9.123

Out of the box that isn't possible because you have two different ways of treating the fragment of your floats. You'll first have to determine how many non-zero numbers there are in your fragment and then act accordingly with sprintf.

<?php

$numbers = array(
    '9.000',
    '9.100',
    '9.120',
    '9.123',
);

foreach ($numbers as $number) {

    $decimals = strlen(str_replace('0','', array_pop(explode('.', $number))));
    $decimals = $decimals ?: 1;
    echo $number . " => " . sprintf("%.{$decimals}f", $number);

    echo "<br/>";

}

怎么样

preg_replace(/\\.$/,'.0',rtrim($value,'0'))

假设数字被编码为或转换为字符串,这是一个通用的方法:

$value = is_numeric($value) ? strval($value + 0) : $value;

My solution is to let php handle it as a number (is *1) and then treat it as a string (my example I was using percentages stored as a decimal with 2 decimal places):

printf('%s%% off', $value*1);

This outputs:

0.00  => 0% off
0.01  => 0.01% off
20.00 => 20% off
20.50 => 20.5% off

rtrim($value, "0") almost works. The problem with rtrim is that it leaves 9.000 as 9.

So just rtrim($value, "0.") and you're done.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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