Rimuovi le cifre zero inutili dai decimali in PHP


164

Sto cercando di trovare un modo rapido per rimuovere zero decimalsda valori numerici come questo:

echo cleanNumber('125.00');
// 125

echo cleanNumber('966.70');
// 966.7

echo cleanNumber(844.011);
// 844.011

Esiste un modo ottimizzato per farlo?


4
Dato che i tuoi valori sono in realtà stringhe, perché non usare semplicemente rtrim () - php.net/manual/en/function.rtrim.php - con uno '0'. come secondo argomento
Mark Baker,

Scusa, non sono stato del tutto chiaro, non sono sempre stringhe, risolvo la domanda.
vitto

9
@Mark Baker: questo è un cattivo approccio poiché il numero 120 verrà ridotto a 12
machineaddict

@machineaddict - lo farebbe se, e solo se, i valori della stringa non avessero un punto decimale ..... tutti quelli citati dall'OP hanno un punto decimale.
Mark Baker,

2
Quindi dovresti aggiungere un avviso in grassetto nella tua risposta, che funziona solo se ci sono decimali.
machineaddict

Risposte:


354

$num + 0 fa il trucco.

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

Internamente, questo equivale al casting con cui fluttuare (float)$numo floatval($num)ma lo trovo più semplice.


45
penso che questo sia un trucco sporco. non lo preferirei perché il codice non dice del suo comportamento come lo floatval()sta facendo.
ESCOBAR

4
floatvalIl comportamento di @ESCOBAR sta restituendo un float. Direi che usarlo come un decimale per i decimali non è nemmeno molto ovvio o pulito.
lafor,

2
Questo è molto poco chiaro. Il nostro team ha appena riscontrato questo nel nostro codice e ha avuto 3 sviluppatori perplessi per qualche tempo. Penso che la risposta di Mark sia un'alternativa migliore. È più lungo, ma il suo intento è chiaro.
jfbalanc,

2
@jfbalanc//COMMENT
Webinan,

1
@ESCOBAR Non proprio, è un metodo ufficialmente suggerito per la tipografia ... cerca "giocoleria di tipo" su php.net
Gergely Lukacsy

101

potresti semplicemente usare la floatvalfunzione

echo floatval('125.00');
// 125

echo floatval('966.70');
// 966.7

echo floatval('844.011');
// 844.011

2
fallisce quando il separatore dei mille è un punto e il segno decimale è una virgola.
Munna Khan,

20

Questo è quello che uso:

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

NB Questo presuppone che .sia il separatore decimale. Ha il vantaggio che funzionerà su numeri arbitrariamente grandi (o piccoli) poiché non esiste un cast float. Inoltre, non trasformerà i numeri in notazione scientifica (ad es. 1.0E-17).


questa non è una soluzione sicura, cosa succede se il prezzo non è decimale per esempio, se lo sviluppatore si moltiplicano il prezzo con un numero intero, allora abbiamo un intero?
Amin

@alex Questa funzione è attiva su numeri interi, float e stringhe.
Aprire il

1
Soluzione perfetta come aiuto per bcmath
Kart Av1k,

17

La semplice aggiunta +alla variabile stringa causerà il typecast a (float) e rimuoverà gli zeri:

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

Per tutti coloro che visitano questo sito con lo stesso problema con le virgole, cambia:

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

per:

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


Se ci sono due zeri da rimuovere, cambia in:

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

Altro qui: numero PHP: punto decimale visibile solo se necessario


10

Se si desidera rimuovere le cifre zero appena prima da visualizzare sulla pagina o sul modello.

È possibile utilizzare la funzione sprintf ()

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

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

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

Grazie ho adorato questa risposta. Questo è molto utile per me.
Sumit Kumar Gupta,

9

Dovresti lanciare i tuoi numeri come float, il che lo farà per te.

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

L'output di questo sarà quello che stai cercando.

42.422005


1
Anche il casting mobile potrebbe corrompere il tuo numero. ad esempio (float)'0.1234567890124567890123456789'diventa 0.12345678901246.
mpen

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

Non c'è nulla che non possa essere risolto con una semplice regex;)

http://xkcd.com/208/


1
Elimina le 0s significative come in "100". Riesce anche a striscia 0s off "100.010".
mpen

2
Tutti state indietro! $x = preg_replace("/(\.0*$)|((?<=\.\d*)0+$)/",'',$x);
Emanuel S.

5

Typecast in a float.

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

2

A causa di questa domanda è vecchia. Innanzitutto, mi dispiace per questo.

La domanda riguarda il numero xxx.xx ma nel caso in cui sia x, xxx.xxxxx o differenza separatore decimale come xxxx, xxxx, può essere più difficile trovare e rimuovere zero cifre dal valore decimale.

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

Ed ecco il codice per il test.

$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

Fai attenzione con l'aggiunta di +0.

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

Il risultato è 1.

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

echo floatval('1000.00');
//1000

Stai rispondendo a una domanda del 2013.
VTodorov,

3
Non è un problema rispondere a una vecchia domanda, se può aiutare i lettori reali
Regno 8

1

Strano, quando ottengo un numero dal database con un tipo "float" e se il mio numero è ex. 10000 quando lo floatval diventa 1.

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

Ho testato tutte le soluzioni sopra ma non ha funzionato.


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

0

Modo complicato ma funziona:

$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

le soluzioni di cui sopra sono il modo ottimale, ma nel caso in cui si desidera avere il proprio è possibile utilizzare questo. Quello che fa questo algoritmo inizia alla fine della stringa e controlla se è 0 , se è impostato su stringa vuota e poi passa al carattere successivo dal retro fino all'ultimo carattere è > 0



0

Questa è la mia piccola soluzione ... Può essere inclusa in una classe e impostare vari

private $ dsepparator = '.'; // decimali private $ tsepparator = ','; // mille

Ciò può essere impostato dal costruttore e modificato in lang degli utenti.

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

}

Quindi ho creato una classe campione con piccoli campioni. Meglio? =)
Paykoman il

0

Questa è la mia soluzione Voglio mantenere la possibilità di aggiungere migliaia di separatori

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

0

Questa è una semplice funzione a una riga che usa rtrim, salva il separatore e il punto decimale:

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

0

Ho trovato questa soluzione la migliore:

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

Semplice e preciso!

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

0

Soluzione definitiva: l'unico modo sicuro è usare regex:

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

funzionerà in ogni caso


0

Quanto segue è molto più semplice

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

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

1
Migliorerebbe la qualità della tua risposta se fornissi una spiegazione di ciò che fa il tuo codice e di come risolverà la domanda originale.
Nigel Ren,

@Nikhil Gyan Sono d'accordo che questa risposta non è eccezionale. Sentiti libero di scendere. Tuttavia, almeno non penso che sia abbastanza brutto per una bandiera di qualità molto bassa
Sam Hartman,

-2

Questo codice rimuoverà zero dopo il punto e restituirà solo due cifre decimali.

$ Numero = 1200,0000;
str_replace ('. 00', '', number_format ($ number, 2, '.', ''));

L'output sarà: 1200

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.