199

I'm trying to find a fast way to remove zero decimals from number values like this:

echo cleanNumber('125.00');
// 125

echo cleanNumber('966.70');
// 966.7

echo cleanNumber(844.011);
// 844.011

Does exists some optimized way to do that?

7
  • 4
    As your values are actually strings, why not simply use rtrim() - php.net/manual/en/function.rtrim.php - with a '0.' as the second argument Commented Jan 25, 2013 at 23:03
  • Sorry, I've been not fully clear, they are not always strings, i fix the question. Commented Jan 25, 2013 at 23:21
  • 14
    @Mark Baker: that is a bad approach as number 120 will be trimmed to 12 Commented Sep 29, 2014 at 8:25
  • @machineaddict - it would if, and only if, the string values didn't have a decimal point..... all those cited by the OP have a decimal point. Commented Sep 29, 2014 at 9:10
  • 3
    Then you should add a bold notice in your answer, that it only works if there are decimals. Commented Sep 29, 2014 at 12:51

30 Answers 30

414

$num + 0 does the trick.

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

Internally, this is equivalent to casting to float with (float)$num or floatval($num) but I find it simpler.

Sign up to request clarification or add additional context in comments.

12 Comments

i think this is a dirty trick. i would not prefer it because the code doesn't tell about his behavior like floatval() is doing it.
@ESCOBAR floatval's behavior is returning a float. I would argue using it as a decimals formatter is not very obvious or clean either.
This is a very unclear. Our team just encountered this in our code, and it had 3 developers puzzled for some time. I think Mark's answer is a better alternative. It is longer, but its intent is clear.
@jfbalanc //COMMENT
@ESCOBAR Not really, it's an officially suggested method for typecasting... search "type juggling" on php.net
|
134

you could just use the floatval function

echo floatval('125.00');
// 125

echo floatval('966.70');
// 966.7

echo floatval('844.011');
// 844.011

4 Comments

it fails when the thousand separator is a dot and decimal mark is a comma.
This is not accurate. floatval('125.00') will return 125.0, not 125 in PHP 8.1.
I'm getting 3000 for 3000.24 in PHP 7.4
It's Deprecated.
32

This is what I use:

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

N.B. This assumes . is the decimal separator. It has the advantage that it will work on arbitrarily large (or small) numbers since there is no float cast. It also won't turn numbers into scientific notation (e.g. 1.0E-17).

5 Comments

this is not a safe solution, what if the price is not decimal?for example if developer multiply the price with an integer then we have an integer
@alex This function works on integers, floats and strings.
Perfect solution as helper for bcmath
This is the only answer that works if the input might contain a comma thousands separator (which fail to cast to float). If the input comes from number_format(), which always includes a decimal separator if a decimal value is provided, the code can be simplified to, e.g.: $output = rtrim(rtrim(number_format($input, 10), '0'), '.')
Works well to parse result after doing number_format(). Thank you!
27

If you want to remove the zero digits just before to display on the page or template.

You can use the sprintf() function

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

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

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

3 Comments

Thanks I loved this answer. This is very helpful for me.
How about to change the decimal separator and thousand separator?
@RayCoder sprintf doesn't have options for adding thousand separators, you can try : sprintf('%s', number_format(2699, 0, '.', ','))
21

Simply adding + to your string variable will cause typecast to (float) and removes zeros:

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)

Comments

19

For everyone coming to this site having the same problem with commata instead, change:

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

to:

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


If there are two zeros to be removed, then change to:

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

More here: PHP number: decimal point visible only if needed

Comments

10

You should cast your numbers as floats, which will do this for you.

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

Output of this will be what you are looking for.

42.422005

1 Comment

Float casting might also corrupt your number. e.g. (float)'0.1234567890124567890123456789' becomes 0.12345678901246.
8

Typecast to a float.

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

Comments

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

There is nothing that can't be fixed with a simple regex ;)

http://xkcd.com/208/

2 Comments

Strips off significant 0s such as in "100". Also fails to strip 0s off "100.010".
Everybody stand back! $x = preg_replace("/(\.0*$)|((?<=\.\d*)0+$)/",'',$x);
4

Sometimes, especially in case of monetary amounts, you want to remove the zeros only if they are 2, you don't want to print € 2.1 instead of € 2.10.

An implementation could be:

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 (string)intval($value);
    }

    return number_format($value, $decimals);
}

Examples of expected outputs:

0.1000 => 0.10
20.000 => 20
1.25 => 1.25

Comments

3

Example 1

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

output

81,500

Example 2

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

output

110,763.14

1 Comment

Code-only answers are not particularly helpful. Please add some descriptions of how this code solves the problem.
2
$str = 15.00;
$str2 = 14.70;
echo rtrim(rtrim(strval($str), "0"), "."); //15
echo rtrim(rtrim(strval($str2), "0"), "."); //14.7

Comments

2

Due to this question is old. First, I'm sorry about this.

The question is about number xxx.xx but in case that it is x,xxx.xxxxx or difference decimal separator such as xxxx,xxxx this can be harder to find and remove zero digits from decimal value.

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

And here is the code for test.

$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>';
}

All tests should be pass and no errors.

Why '-12.345,000000,000' will be '-12.345,000000' not '-12.345'?
Because this function is for remove zero digits (include zero trails) from decimal value. It is not validation for the correct number format. That should be another function.

Why always return as string?
Because it is better to use in calculation with bcxxx functions, or use with big number.

2 Comments

You are not removing 0 here? Line 4: '12,345.67890',// 12,345.67890
@Siwei Updated my function and tests. It is now able to remove .0000 and change .123450 to be .12345. However, I don't think it should remove incorrect number format like 123.456.789 because it should be in validation function, or Do you have any idea about this?
1

Thats my small solution... Can included to a class and set vars

private $dsepparator = '.'; // decimals private $tsepparator= ','; // thousand

That can be set by constructor and change to users 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
     */

}

1 Comment

So i have build a sample class with little samples. Better? =)
1

I found this solution is the best:

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

Comments

1

The following is much simpler

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

Comments

1

You can try the following:

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

Comments

0

Complicated way but works:

$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

the solutions above are the optimal way but in case you want to have your own you could use this. What this algorithm does it starts at the end of string and checks if its 0, if it is it sets to empty string and then goes to the next character from back untill the last character is > 0

Comments

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

2 Comments

It would improve the quality of your answer if you provided an explanation of what your code does and how it will solve the original question.
@Nikhil Gyan I agree this answer isn't great. Feel free to ote down. However, I at least don't think it is bad enough for very low quality flag
0

You can use:

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

Comments

0

This is my solution. I want to keep ability to add thousands separator

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

Comments

0

This is a simple one line function using rtrim, save separator and decimal point :

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

Comments

0

Simple and accurate!

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

Comments

0

I use this simple code:

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;

Seems a bit too easy to be the really correct solution, but it works just fine for me. You should do some tests with the inputs you'll be getting before using this.

Comments

0

Assuming the amount is a string with 2 decimal places, then you can use:

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

That will work as expected for ?any? currency, like $500.00 and R$ 500,00.

Comments

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

}

//output: 10.0.1.0 => 10.0.1

//output: 10.0.1 => 10.0.1

//output: 10.1.2 => 10.1.2

//output: 10.0.0 => 10

This function will only remove the trailing zero decimals

Comments

0

The easiest way to use round()

function cleanNumber( $amount = 0, $min = 0, $max = 8 )
    {
        $amount = round($amount, $max);
        $expl = explode('.', $amount);
        
        if (!isset($expl[1]) || $expl[1] < $min){
            $amount = sprintf('%02.'.$min.'F', $amount);
        }
        return $amount;
    }
    
    
echo cleanNumber('125.00').'   ';

echo cleanNumber('966.70').'   ';

echo cleanNumber(844.011).'   ';

echo cleanNumber(844.00000000000000000000000000000000, 2, 8).'   ';

echo cleanNumber(844.77777777777777777777777777777777, 2, 8).'   ';

PHP Sandbox

Comments

-1

This Code will remove zero after point and will return only two decimal digits.

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

Output will be: 1200

1 Comment

This actually made sense because sometimes (monetary amounts) you want to remove the zeros if they are 2, you don't want to print € 2.1 instead of € 2.10
-1

Ultimate Solution: The only safe way is to use regex:

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

it will work for any case

Comments

-1

ADVICE: the marked answer works ONLY for numbers below 1000 or if the value greater than 1000 doesn't have a number format like '#,###.##'.

A better approximation is like the following (the fraction algo at https://gist.github.com/graceman9/2f912b28e6c8aecf4421):

$value = 125.00; // or 1250.00
$whole = floor($value); // 125
$fraction = round($value - $whole, 2);
$result = number_format($value, $fraction >= 0.01 ? 2 : 0, ",", "."); // Or whatever number format that you need

1 Comment

The marked answer works for numbers of any value. It doesn't work for string representation of numbers containing thousands separator(s) (which you assume is , but can be ' or a half-space or a bunch of other characters). Neither does your answer, BTW. You can't floor or subtract from a string in a #,###.## format. Also, OP wanted to drop insignificant zeroes from the decimal part, not round it to 2 digits. 0.23600 should become 0.236, not 0.24.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.