round - reducir los decimales en php
PHP bajando decimales sin redondear (10)
Las respuestas de RenaPot , IsisCode , goredwards no son correctas.
Debido a cómo funciona float en las computadoras (en general), float no es exacto.
Para replicar el problema:
floor(19.99 * 100);// Outputs 1998 instead of 1999
floor(19.99 * 100);// Outputs 509 instead of 510
Dentro de PHP internamente, 19.99 * 100
resulta en algo así como 1998.999999999999999
, que cuando hacemos floor
de eso, obtenemos 1998
.
Solución:
Solución 1: use la biblioteca bcmath (sugerida por @SamyMassoud) si la tiene instalada (es posible que algunos servidores de alojamiento compartido no la tengan instalada de manera predeterminada). Al igual que:
//floor(19.99 * 100);// Original
floor(bcmul(19.99, 100));// Outputs 1999
Solución 2: manipulación de cuerdas (mi recomendación):
// Works with positive and negative numbers, and integers and floats and strings
function withoutRounding($number, $total_decimals) {
$number = (string)$number;
if($number === '''') {
$number = ''0'';
}
if(strpos($number, ''.'') === false) {
$number .= ''.'';
}
$number_arr = explode(''.'', $number);
$decimals = substr($number_arr[1], 0, $total_decimals);
if($decimals === false) {
$decimals = ''0'';
}
$return = '''';
if($total_decimals == 0) {
$return = $number_arr[0];
} else {
if(strlen($decimals) < $total_decimals) {
$decimals = str_pad($decimals, $total_decimals, ''0'', STR_PAD_RIGHT);
}
$return = $number_arr[0] . ''.'' . $decimals;
}
return $return;
}
// How to use:
withoutRounding(19.99, 2);// Return "19.99"
withoutRounding(1.505, 2);// Return "1.50"
withoutRounding(5.1, 2);// Return "5.10"
Quiero dejar decimales sin redondear. Por ejemplo, si tengo 1.505, quiero soltar el último decimal y el valor debería ser 1.50. ¿Existe tal función en PHP?
Necesitas floor() de esta manera:
$rounded = floor($float*100)/100;
O lo conviertes en entero:
$rounded = 0.01 * (int)($float*100);
De esta manera no se redondeará.
Para hacer esto con precisión para los números + ve y -ve que necesita usar:
- la función php floor()
para números + ve
- la función php ceil()
para -ve números
function truncate_float($number, $decimals) {
$power = pow(10, $decimals);
if($number > 0){
return floor($number * $power) / $power;
} else {
return ceil($number * $power) / $power;
}
}
La razón de esto es que floor()
siempre redondea el número hacia abajo , no hacia cero.
es decir, floor()
redondea efectivamente los números -ve hacia un valor absoluto mayor
por ejemplo, floor(1.5) = 1
mientras que floor(-1.5) = -2
Por lo tanto, para la multiply by power, remove decimals, divide by power
método de truncado de multiply by power, remove decimals, divide by power
:
- floor()
solo funciona para números positivos
- ceil()
solo funciona para números negativos
Para probar esto, copie el siguiente código en el editor de http://phpfiddle.org/lite (o similar):
<div>Php Truncate Function</div>
<br>
<?php
function truncate_float($number, $places) {
$power = pow(10, $places);
if($number > 0){
return floor($number * $power) / $power;
} else {
return ceil($number * $power) / $power;
}
}
// demo
$lat = 52.4884;
$lng = -1.88651;
$lat_tr = truncate_float($lat, 3);
$lng_tr = truncate_float($lng, 3);
echo ''lat = '' . $lat . ''<br>'';
echo ''lat truncated = '' . $lat_tr . ''<br>'';
echo ''lat = '' . $lng . ''<br>'';
echo ''lat truncated = '' . $lng_tr . ''<br><br>'';
// demo of floor() on negatives
echo ''floor (1.5) = '' . floor(1.5) . ''<br>'';
echo ''floor (-1.5) = '' . floor(-1.5) . ''<br>'';
?>
Podemos usar funciones bc si están disponibles:
echo bcadd(sprintf(''%F'', 5.445), ''0'', 2); // => 5.44
echo sprintf(''%.2F'', 5.445); // => 5.45
Sé que esta es una respuesta tardía pero aquí hay una solución simple. Usando el ejemplo OP de 1.505, simplemente puede usar lo siguiente para llegar a 1.50.
function truncateExtraDecimals($val, $precision) {
$pow = pow(10, $precision);
$precise = (int)($val * $pow);
return (float)($precise / $pow);
}
Esto administra valores tanto positivos como negativos sin la preocupación de filtrar qué función usar y presta para corregir resultados sin preocuparse de qué otras funciones podrían hacer con el valor.
$val = 1.509;
$truncated = sprintf(''%.2f'', truncateExtraDecimals($val, 2));
echo "Result: {$truncated}";
Result: 1.50
El sprintf es necesario para obtener exactamente 2 decimales para mostrar, de lo contrario, el Resultado habría sido 1.5 en lugar de 1.50.
Tal vez sea demasiado tarde, pero aquí hay un buen enfoque:
$getTruncatedValue = function( $value, $precision )
{
//Casts provided value
$value = ( string )$value;
//Gets pattern matches
preg_match( "/(-+)?/d+(/./d{1,".$precision."})?/" , $value, $matches );
//Returns the full pattern match
return $matches[0];
};
var_dump
(
$getTruncatedValue(1.123,1), //string(3) "1.1"
$getTruncatedValue(1.345,2), //string(4) "1.34"
$getTruncatedValue(1.678,3), //string(5) "1.678"
$getTruncatedValue(1.90123,4) //string(6) "1.9012"
);
- El único escollo en este enfoque puede ser la necesidad de usar una Expresión Regular (que a veces podría traer una penalización de rendimiento).
Nota: es bastante difícil encontrar un enfoque nativo para truncar decimales, y creo que no es posible realizar eso usando sprintf y otras funciones relacionadas con cadenas.
puede convertir 1.505
a tipo de datos de cadena y hacer uso de substring()
para truncar el último carácter.
Y de nuevo convertirlo en integer
.
solo haz (int) $number;
para obtener entero
$float = 1.505;
echo sprintf("%.2f", $float);
//outputs 1.50
$num = 118.74999669307;
$cut = substr($num, 0, ((strpos($num, ''.'')+1)+2));`
// Cut the string from first character to a length of 2 past the decimal.
/ substr(cut what, start, ( (find position of decimal)+decimal itself)+spaces after decimal) )
echo $cut;
esto le ayudará a acortar el valor flotante sin redondearlo.