Eliminar dígitos cero inútiles de decimales en PHP

163

Estoy tratando de encontrar una forma rápida de eliminar zero decimalsvalores numéricos como este:

echo cleanNumber('125.00');
// 125

echo cleanNumber('966.70');
// 966.7

echo cleanNumber(844.011);
// 844.011

¿Existe alguna forma optimizada de hacer eso?

vitto
fuente
44
Como sus valores son en realidad cadenas, ¿por qué no simplemente usar rtrim () - php.net/manual/en/function.rtrim.php - con un '0'? como segundo argumento
Mark Baker
Lo siento, no he sido completamente claro, no siempre son cadenas, solucioné la pregunta.
vitto
9
@ Marcos de Baker: que es un mal enfoque como el número 120 se recortará a 12
machineaddict
@machineaddict: lo haría si, y solo si, los valores de cadena no tuvieran un punto decimal ... todos los citados por el OP tienen un punto decimal.
Mark Baker
2
Luego debe agregar un aviso en negrita en su respuesta, que solo funciona si hay decimales.
machineaddict

Respuestas:

354

$num + 0 Hace el truco.

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

Internamente, esto es equivalente a lanzar para flotar con (float)$numo floatval($num)pero me parece más simple.

lafor
fuente
45
Creo que este es un truco sucio. No lo preferiría porque el código no dice sobre su comportamiento como lo floatval()está haciendo.
ESCOBAR
44
floatvalEl comportamiento de @ESCOBAR está devolviendo un flotador. Yo diría que usarlo como formateador de decimales tampoco es muy obvio o limpio.
2014
2
Esto es muy poco claro. Nuestro equipo acaba de encontrar esto en nuestro código, y tenía 3 desarrolladores desconcertados por algún tiempo. Creo que la respuesta de Mark es una mejor alternativa. Es más largo, pero su intención es clara.
jfbalanc
2
@jfbalanc//COMMENT
Webinan 01 de
1
@ESCOBAR En realidad no, es un método sugerido oficialmente para la conversión de texto ... busque "malabarismo de tipos" en php.net
Gergely Lukacsy
101

podrías usar la floatvalfunción

echo floatval('125.00');
// 125

echo floatval('966.70');
// 966.7

echo floatval('844.011');
// 844.011
DiverseAndRemote.com
fuente
2
falla cuando el separador de miles es un punto y la marca decimal es una coma.
Munna Khan
20

Esto es lo que uso:

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

NB Esto supone que .es el separador decimal. Tiene la ventaja de que funcionará en números arbitrariamente grandes (o pequeños) ya que no hay un elenco flotante. Tampoco convertirá los números en notación científica (por ejemplo, 1.0E-17).

mpen
fuente
esto no es una solución segura, ¿y si el precio no es decimal, por ejemplo, si se multiplica el precio de desarrolladores con un entero, entonces tenemos un número entero?
Amin
@alex Esta función funciona en enteros, flotantes y cadenas.
mpen
1
Solución perfecta como ayuda para bcmath
Kart Av1k
17

Simplemente agregar +a su variable de cadena hará que el encasillado (flotante) y elimine ceros:

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)
Alexander Yancharuk
fuente
13

Para todos los que visiten este sitio y tengan el mismo problema con los comas, cambie:

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

a:

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


Si hay que eliminar dos ceros , cambie a:

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

Más aquí: número PHP: punto decimal visible solo si es necesario

Kai Noack
fuente
10

Si desea eliminar los dígitos cero justo antes de mostrar en la página o plantilla.

Puedes usar la función sprintf ()

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

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

‌‌‌‌sprintf('%g',844.011);
//844.011
Hemerson Varela
fuente
Gracias, me encantó esta respuesta. Esto es muy útil para mi.
Sumit Kumar Gupta
9

Debes lanzar tus números como flotadores, lo que hará esto por ti.

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

La salida de esto será lo que estás buscando.

42.422005

Sajan Parikh
fuente
1
El lanzamiento flotante también puede corromper tu número. por ejemplo se (float)'0.1234567890124567890123456789'convierte 0.12345678901246.
mpen
8
$x = '100.10'; 
$x = preg_replace("/\.?0*$/",'',$x); 
echo $x;

No hay nada que no se pueda solucionar con una simple expresión regular;)

http://xkcd.com/208/

Dakkaron
fuente
1
Se quita 0s significativos como en "100". También falla para despojar 0s fuera "100.010".
mpen
2
¡Todos retrocedan! $x = preg_replace("/(\.0*$)|((?<=\.\d*)0+$)/",'',$x);
Emanuel S.
5

Tipografía a float.

$int = 4.324000;
$int = (float) $int;
Joseph A.
fuente
2

Debido a esta pregunta es vieja. Primero, lo siento por esto.

La pregunta es sobre el número xxx.xx, pero en caso de que sea x, xxx.xxxxx o un separador decimal de diferencia como xxxx, xxxx, esto puede ser más difícil de encontrar y eliminar dígitos cero del valor decimal.

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

Y aquí está el código para la prueba.

$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, ','));
}
vee
fuente
2

Tenga cuidado al agregar +0.

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

El resultado de esto es 1.

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

echo floatval('1000.00');
//1000
Cebolla
fuente
Estás respondiendo una pregunta de 2013.
VTodorov
3
No es un problema de responder a una vieja pregunta, si puede ayudar a los lectores reales
Reign.85
1

Extraño, cuando obtengo un número de la base de datos con un tipo "flotante" y si mi número es ex. 10000 cuando lo floto, se convierte en 1.

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

He probado todas las soluciones anteriores pero no funcionó.

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

Forma complicada pero funciona:

$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

Las soluciones anteriores son la forma óptima, pero en caso de que desee tener la suya, puede usarla. Lo que hace este algoritmo comienza al final de la cadena y comprueba si es 0 , si es así, se establece en una cadena vacía y luego pasa al siguiente carácter desde atrás hasta que el último carácter sea > 0

GGio
fuente
0

Puedes usar:

print (floatval)(number_format( $Value), 2 ) );    
MUNEERPASHA GADAD
fuente
0

Esa es mi pequeña solución ... Se puede incluir en una clase y configurar vars

private $ dsepparator = '.'; // decimales private $ tsepparator = ','; // mil

Eso puede establecerlo el constructor y cambiarlo a los usuarios 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
fuente
Así que he creado una clase de muestra con pequeñas muestras. ¿Mejor? =)
Paykoman
0

Esta es mi solución Quiero mantener la capacidad de agregar separador de miles

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

Esta es una función simple de una línea que usa rtrim, guardar separador y punto decimal:

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

Encontré que esta solución es la mejor:

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

Simple y preciso!

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

Solución definitiva: la única forma segura es usar regex:

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

funcionará para cualquier caso

Yohanes AI
fuente
0

Lo siguiente es mucho más simple

if(floor($num) == $num) {
    echo number_format($num);
} else {
    echo $num;
}
Nemrod Mondez
fuente
-1
$value = preg_replace('~\.0+$~','',$value);
Nikhil Gyan
fuente
1
Mejoraría la calidad de su respuesta si proporcionara una explicación de lo que hace su código y cómo resolverá la pregunta original.
Nigel Ren
@Nikhil Gyan Estoy de acuerdo con que esta respuesta no es genial. Siéntase libre de ote down. Sin embargo, al menos no creo que sea lo suficientemente malo para una bandera de muy baja calidad
Sam Hartman
-2

Este Código eliminará cero después del punto y devolverá solo dos dígitos decimales.

$ número = 1200.0000;
str_replace ('. 00', '', number_format ($ número, 2, '.', ''));

La salida será: 1200

Ashish Pathak
fuente