Almacenar precios como enteros en PHP

Seguro que muchas veces te has encontrado con problemas de redondeo y precisión cuando trabajas con precios (en PHP y en otros lenguajes). Muy a menudo los precios se almacenan y se opera con ellos usando variables tipos float o double y lo más probable es que hayas sufrido a causa del redondedo..

Un sencillo truco para evitarlo es almacenar los precios como números enteros. Luego, para mostrarlos al usuario se puede dividir por cien y listo:

$precioArticulo1 = 2036;
$precioArticulo2 = 1277;

$precioTotal = $precioArticulo1 + $precioArticulo2;

echo $precioTotal / 100 . PHP_EOL;

Entonces ¿es una buena idea usar números enteros?

Mmm, pues en mi opinión no.

¡Pero si las sumas y restas funcionan genial!

Eso es cierto. Pero ¿y qué pasa cuando tienes que aplicar un impuesto? Por ejemplo un impuesto del 21%:

$precio = 128;
$iva = 1.21;

echo $precio * $iva . PHP_EOL;

¡No pasa nada! Usa el impuesto como 121 en lugar de 1.21:

$precio = 128;
$iva = 121;

echo ( $precio * $iva ) / 100 . PHP_EOL;

Mmmm, ya ¿y qué pasa con las divisiones? ¿Cómo quitas el impuesto a ese precio? Tienes que dividir entre 1.21:

$precio = 128.22;
$iva = 1.21;

echo ( $precio * $iva ) . PHP_EOL;

¡Pues mira que eres tonto! ¡Haces lo mismo y funciona!

Vale, que sí, parece que tienes razón. Usar enteros parece muy bonito pero no lo es. Tiene algunos problemas y es más trabajo y propenso a errores (en algún punto te puedes olvidar de convertir entre la moneda «normal» y la fraccionaria.

Entonces ¿uso float y double?

Uy, no, eso sí que te va a dar problemas. Mejor huye de estos dos tipos de datos.

¿Y entonces qué hago?

Bueno, pues tienes la opción de usar alguna librería que se maneje bien con monedas. A mí me gusta la de moneyphp/money:

https://github.com/moneyphp/money

¿Y en una base de datos? ¿Cómo almaceno los precios?

Pues en una base de datos la práctica habitual es usar el tipo DECIMAL. Podrías usar enteros y, con suerte, no tendrías muchos problemas. Pero ¿para qué hacerlo si tienes DECIMAL que es lo ideal?

1 comentario en “Almacenar precios como enteros en PHP”

Me siento solo, dime algo...