Comment Lua gère les nombres entiers et flottants?

11

Autant que je me souvienne de la programmation, on m'a appris à ne pas comparer les nombres à virgule flottante pour l'égalité. Maintenant, en lisant Programmation dans Lua sur le numbertype Lua , j'ai trouvé ce qui suit:

Le type de nombre représente des nombres réels (virgule flottante double précision). Lua n'a pas de type entier, car il n'en a pas besoin. Il y a une idée fausse répandue sur les erreurs arithmétiques à virgule flottante et certaines personnes craignent que même un simple incrément puisse devenir bizarre avec des nombres à virgule flottante. Le fait est que, lorsque vous utilisez un double pour représenter un entier, il n'y a aucune erreur d'arrondi (sauf si le nombre est supérieur à 100 000 000 000 000). Plus précisément, un nombre Lua peut représenter n'importe quel entier long sans problème d'arrondi. De plus, la plupart des processeurs modernes font une arithmétique en virgule flottante aussi rapide (ou même plus rapide que) l'arithmétique entière.

Est-ce vrai pour toutes les langues? Fondamentalement, si nous n'allons pas au-delà de la virgule flottante en double, nous sommes en sécurité en arithmétique entière? Ou, pour être plus en phase avec le titre de la question, y a-t-il quelque chose de spécial que Lua fait avec son numbertype, donc cela fonctionne bien en tant que type entier et flottant?

Petr Abdulin
la source
Voir aussi stackoverflow.com/questions/1848700/…
Joonas Pulakka
@JoonasPulakka merci, c'est un ajout très précieux.
Petr Abdulin

Réponses:

11

Lua prétend que les nombres à virgule flottante peuvent représenter des nombres entiers aussi exactement que les types entiers, et je suis enclin à être d'accord. Il n'y a pas de représentation imprécise d'une partie numérique fractionnaire à traiter. Que vous stockiez un entier dans un type entier ou le stockiez dans la mantisse d'un nombre à virgule flottante, le résultat est le même: cet entier peut être représenté exactement, tant que vous ne dépassez pas le nombre de bits dans la mantisse , + 1 bit dans l'exposant.

Bien sûr, si vous essayez de stocker un nombre réel à virgule flottante (par exemple 12,345) dans une représentation à virgule flottante, tous les paris sont désactivés, donc votre programme doit être clair que le nombre est vraiment un entier authentique qui ne déborde pas le mantisse, afin de la traiter comme un entier réel (c'est-à-dire en ce qui concerne la comparaison de l'égalité).

Si vous avez besoin de plus de précision entière que cela, vous pouvez toujours utiliser une bibliothèque de précision arbitraire .

Lectures complémentaires
Quelle est la valeur maximale d'un nombre en Lua?

Robert Harvey
la source
Qu'en est-il de leur deuxième argument, à savoir que la virgule flottante est aussi rapide ou plus rapide que l'arithmétique entière dans les processeurs modernes? Cela me semble douteux, même lorsque j'utilise des nombres à virgule flottante pour effectuer une arithmétique entière.
Andres F.
2
@AndresF. Je ne vois pas comment c'est plus rapide, sauf si vous éliminez un casting en utilisant un seul type numérique au lieu de deux.
Robert Harvey
D'accord. Ça n'a aucun sens pour moi. Je me demande si c'est sorti de son contexte ...
Andres F.
1
Des entiers suffisamment grands ne peuvent pas être stockés exactement dans un objet à virgule flottante. Un 64 bits doublea environ 51 bits de mantisse; les entiers impairs supérieurs à environ 2 ** 51 auront des erreurs d'arrondi. Un entier 64 bits peut stocker des valeurs entières plus grandes exactement, car il ne consacre aucun bit à un exposant.
Keith Thompson
@KeithThompson: Je pensais que c'était implicite dans ma réponse quand j'ai dit "stocké dans la mantisse". Cependant, je vais modifier la réponse pour clarifier.
Robert Harvey
6

Les doubles sont stockés sous forme de mantisse et d'exposant. Voir le format pour plus d'informations. Fondamentalement, tous les nombres sont de la forme: mantisse * 2 exposant . Pour tout entier inférieur à 2 52 , l'exposant sera nul, ce qui rend la mantisse bit pour bit équivalent à un entier non signé de 52 bits. Un bit de signe distinct est utilisé pour indiquer des nombres négatifs.

En fait, même certains entiers supérieurs à 2 52 peuvent être représentés exactement, tant que tous les chiffres après le 52 ème sont des zéros. De plus, certaines fractions, comme 0,5, peuvent être représentées exactement. Ce n'est que lorsque la fraction se répète en continu (comme 1/3) dans la base 2, ou nécessite autrement trop de bits après le point de radix que vous perdez en précision.

Karl Bielefeldt
la source
Ce n'est pas à cause de la répétition continue des décimales. C'est parce que de nombreux nombres décimaux (base dix) ne peuvent pas être représentés exactement comme une puissance de deux.
Robert Harvey
3
Dans la base 2, les nombres qui ne peuvent pas être représentés exactement se répéteraient continuellement. Par exemple, 0,1 décimal devient 0,0 (0011) en binaire, le 0011 se répétant en continu.
Karl Bielefeldt
3
Oui, exactement. Mais ne pas répéter en base 10. Répéter en base 2.
Robert Harvey