2010-03-23 10 views
11

niño, éste es realmente raro. Espero que el siguiente código para imprimir 1990, pero imprime 1989!¿Por qué `intval (19.9 * 100)` es igual a `1989`?

$val = '$19.9'; 

$val = preg_replace('/[^\d.]/','',$val); 
$val = intval($val * 100); 

echo $val; 

¿Por qué demonios sucede esto?

Editar: y este código:

$val = '$19.9'; 
$val = preg_replace('/[^\d.]/','',$val); 
echo $val . "<br>"; 
$val = $val * 100; 
echo $val . "<br>"; 
$val = intval($val); 
echo $val; 

Lienzo:

19.9 
1990 
1989 

¿Por qué intval(1990) igual 1989 ???

+0

'intval ('1990')' me da 1990. Voy a tratar de comprobar su caso fuera. Por el momento, intente dar un título más relevante a su pregunta. – zneak

+0

No, no. 'intval ('1990')' da 1990, lo que digo es que el ejemplo sugiere indirectamente que 'intval (1990)' es igual a '1989' –

+1

Este problema ha sido discutido en casi todos los otros idiomas conocidos por el hombre en este sitio ... – animuson

Respuesta

17

Esta es una precisión inherente a la emisión de números de punto en PHP, y un montón de otras lenguas flotante. Este informe de error se analiza un poco, en el contexto de la fundición como un int:

http://bugs.php.net/bug.php?id=33731

Trate round($val * 100) lugar.

+0

Sí, lo tienes. – zneak

+0

Bien, 'redondo' da la respuesta esperada. ¿Qué implicaciones tiene el uso de 'round' en lugar de' intval'? –

+0

como yo lo entiendo, al convertir el valor a un int usando 'intval()', básicamente corta el valor del flotante después del decimal en lugar de redondearlo. – Funkatron

0

$val es un número de coma flotante - el resultado de "19.9" * 100. Los números de coma flotante no son 100% precisos en ningún idioma (esto es por diseño). Si necesita una precisión decimal del 100% para los valores en dólares, debe usar números enteros y realizar todos los cálculos con centavos (p. Ej., "$19.90" debe ser 1990).

+0

Entonces, ¿qué estás diciendo? –

+0

Usar números enteros no es realmente una buena solución. ¿Tiene que lidiar con cantidades superiores a 20 millones? Oops. ¿Diferentes monedas, no todas tienen 100 subunidades? No se puede hacer. –

+0

@Michael - PHP no tiene enteros de 64 bits? Creo que las diferentes monedas no son un problema, ya que no se pueden comparar directamente entre sí de todos modos. –

4

La respuesta habitual a esta clase de pregunta es para leer What Every Computer Scientist Should Know About Floating-Point Arithmetic.

+1

... que desafortunadamente no ayuda en absoluto a las personas que hacen este tipo de preguntas básicas. –

+1

y ni siquiera ayudamos a aquellos de nosotros que producimos muchos códigos, pero no somos matemáticos. – wadesworld

+0

Vi en otra respuesta que alguien había escrito una versión simplificada de este documento, pero no recuerdo qué pregunta ni quién era. – Powerlord

2

¿Por qué intval (1990) 1989 iguales ???

Porque eres no teniendo intval(1990). Está tomando intval($val * 100) donde $val es un número cercano, pero ligeramente más pequeño que, 19.9.

Leer The Floating-Point Guide entender por qué esto es así.

cuanto a cómo solucionarlo: no lo utilices valores de punto flotante por dinero. En PHP, debe usar BCMath en su lugar.

Cuestiones relacionadas