¿Cómo maneja Lua los números enteros y flotantes?

11

Por lo que recuerdo, yo mismo estaba programando, me enseñaron a no comparar números de coma flotante por igualdad. Ahora, mientras leía Programación en Lua sobre el numbertipo de Lua , encontré lo siguiente:

El tipo de número representa números reales (punto flotante de precisión doble). Lua no tiene un tipo entero, ya que no lo necesita. Existe una idea errónea generalizada sobre los errores aritméticos de punto flotante y algunas personas temen que incluso un simple incremento pueda volverse extraño con los números de punto flotante. El hecho es que, cuando usa un doble para representar un número entero, no hay ningún error de redondeo (a menos que el número sea mayor que 100,000,000,000,000). Específicamente, un número Lua puede representar cualquier número entero largo sin problemas de redondeo. Además, la mayoría de las CPU modernas hacen aritmética de punto flotante tan rápido (o incluso más rápido que) aritmética de enteros.

¿Es eso cierto para todos los idiomas? Básicamente, si no vamos más allá del punto flotante en dobles, ¿estamos seguros en la aritmética de enteros? O, para estar más en línea con el título de la pregunta, ¿hay algo especial que Lua haga con su numbertipo para que funcione bien como tipo entero y tipo de punto flotante?

Petr Abdulin
fuente
Ver también stackoverflow.com/questions/1848700/…
Joonas Pulakka
@JoonasPulakka gracias, esa es una adición bastante valiosa.
Petr Abdulin

Respuestas:

11

Lua afirma que los números de coma flotante pueden representar números enteros tan exactamente como los tipos enteros, y me inclino a estar de acuerdo. No hay una representación imprecisa de una parte numérica fraccionaria con la que lidiar. Ya sea que almacene un número entero en un tipo entero o lo almacene en la mantisa de un número de coma flotante, el resultado es el mismo: ese entero puede representarse exactamente, siempre y cuando no exceda el número de bits en la mantisa , + 1 bit en el exponente.

Por supuesto, si intenta almacenar un número de punto flotante real (por ejemplo, 12.345) en una representación de punto flotante, todas las apuestas están desactivadas, por lo que su programa debe tener claro que el número es realmente un entero genuino que no desborda el mantissa, para tratarlo como un entero real (es decir, con respecto a la comparación de la igualdad).

Si necesita más precisión entera que eso, siempre puede emplear una biblioteca de precisión arbitraria .

Lecturas adicionales
¿Cuál es el valor máximo de un número en Lua?

Robert Harvey
fuente
¿Qué pasa con su segundo argumento, es decir, que el punto flotante es tan rápido o más rápido que la aritmética de enteros en las CPU modernas? Me suena dudoso, incluso cuando se usan números de coma flotante para realizar aritmética de enteros.
Andres F.
2
@AndresF. No veo cómo es más rápido, a menos que esté eliminando un yeso utilizando un solo tipo numérico en lugar de dos.
Robert Harvey
Convenido. No tiene ningún sentido para mí. Me pregunto si está fuera de contexto ...
Andres F.
1
Los enteros suficientemente grandes no se pueden almacenar exactamente en un objeto de punto flotante. Un 64 bits doubletiene aproximadamente 51 bits de mantisa; enteros impares mayores que aproximadamente 2 ** 51 tendrán errores de redondeo. Un número entero de 64 bits puede almacenar valores enteros más grandes exactamente, ya que no dedica ningún bit a un exponente.
Keith Thompson
@KeithThompson: pensé que eso estaba implícito en mi respuesta cuando dije "almacenado en la mantisa". Sin embargo, editaré la respuesta para aclarar.
Robert Harvey
6

Los dobles se almacenan como una mantisa y un exponente. Vea el formato para más información. Básicamente, todos los números tienen la forma: mantisa * 2 exponente . Para cualquier número entero menor que 2 52 , el exponente será cero, lo que hace que la mantisa sea bit por bit equivalente a un número entero sin signo de 52 bits. Se usa un bit de signo separado para indicar números negativos.

De hecho, incluso algunos números enteros mayores que 2 52 se pueden representar con exactitud, siempre y cuando todos los dígitos pasados los 52 nd son ceros. Además, algunas fracciones, como 0.5, se pueden representar exactamente. Es solo cuando la fracción se repite continuamente (como 1/3) en la base 2, o de lo contrario requiere demasiados bits más allá del punto de raíz que pierde precisión.

Karl Bielefeldt
fuente
No se debe a los decimales que se repiten continuamente. Es porque muchos números decimales (base diez) no pueden representarse exactamente como una potencia de dos.
Robert Harvey
3
En la base 2, los números que no se pueden representar exactamente se repetirían continuamente. Por ejemplo, 0.1 decimal se convierte en 0.0 (0011) en binario, con el 0011 repitiéndose continuamente.
Karl Bielefeldt
3
Sí exactamente. Pero no repitiendo en la base 10. Repitiendo en la base 2.
Robert Harvey