Maison >développement back-end >Tutoriel Python >Une brève discussion sur les raisons pour lesquelles les opérations en virgule flottante produisent des erreurs

Une brève discussion sur les raisons pour lesquelles les opérations en virgule flottante produisent des erreurs

青灯夜游
青灯夜游avant
2021-07-15 18:53:0210471parcourir

Cet article utilise Python comme exemple pour expliquer pourquoi les opérations en virgule flottante produisent des erreurs ? Veuillez présenter les circonstances dans lesquelles des erreurs peuvent survenir ? et comment le résoudre ? J'espère que ça aide.

Une brève discussion sur les raisons pour lesquelles les opérations en virgule flottante produisent des erreurs

[Recommandation associée : Tutoriel vidéo Python3 ]

Tout le monde rencontrera la soi-disant erreur de virgule flottante lors de l'écriture de code. Si vous n'êtes pas entré dans le gouffre de l'erreur de virgule flottante, je peux seulement dire que. tu as trop de chance.

Prenons le Python dans l'image ci-dessous comme exemple. 0.1 + 0.2 n'est pas égal à 0.3, et 8.7 / 10 n'est pas égal à 0.87, mais 0.869999… C'est vraiment étrange

Une brève discussion sur les raisons pour lesquelles les opérations en virgule flottante produisent des erreurs

Mais ce n'est certainement pas un bug des enfers. , et il n'y a pas non plus de problème avec la conception de Python. C'est le résultat inévitable des nombres à virgule flottante lors de l'exécution d'opérations, donc c'est la même chose même en JavaScript ou dans d'autres langages :

Une brève discussion sur les raisons pour lesquelles les opérations en virgule flottante produisent des erreurs

Comment un ordinateur stocke-t-il un entier. (Entier)

Parlons de pourquoi il existe Avant de parler des erreurs à virgule flottante, parlons de la façon dont les ordinateurs utilisent 0 et 1 pour représenter un entier Tout le monde devrait connaître le binaire : par exemple, 101 représente 2^2 + 2. ^0$, soit 5, 1010 représente 2^3 + 2^1$ soit 10.

Une brève discussion sur les raisons pour lesquelles les opérations en virgule flottante produisent des erreurs

S'il s'agit d'un entier non signé de 32 bits, cela signifie qu'il a 32 positions où 0 ou 1 peut être placé, donc la valeur minimale est 0000...0000, qui est 0, et la valeur maximale 1111...1111 représente 2 $^{ 31} + 2^{ 30} + ... + 2^1 + 2^0$, soit 4294967295

Du point de vue de la permutation et de la combinaison, car chaque bit peut être 0 ou 1, la valeur de la variable entière est de 2 $^{32} $ de possibilités, il peut donc avec précision exprimer n'importe quelle valeur entre 0 et $2^{23} - 1$ sans aucune erreur.

Point flottant

Bien qu'il existe de nombreux entiers de 0 à $2^{23} - 1$, leur nombre est limité après tout, qui peut atteindre 2$^{32}$ Un seul mais flottant- ; les nombres ponctuels sont différents. On peut y penser de cette façon : il n'y a que dix entiers compris entre 1 et 10, mais il existe une infinité de nombres à virgule flottante, comme 5.1, 5.11, 5.111, etc., c'est impossible. pour les énumérer. Mais comme il n'y a que 2³² possibilités dans l'espace 32 bits, afin d'insérer tous les nombres à virgule flottante dans cet espace 32 bits, de nombreux fabricants de processeurs ont inventé diverses méthodes de représentation des nombres à virgule flottante, mais si chaque processeur Les formats sont tous différents et encombrants, donc en fin de compte, la norme IEEE 754 publiée par l'IEEE a été utilisée comme norme générale de calcul en virgule flottante. Les processeurs d'aujourd'hui sont également conçus selon cette norme.

IEEE 754

IEEE 754 définit beaucoup de choses, notamment la représentation de la simple précision (32 bits), de la double précision (64 bits) et des valeurs spéciales (infini, NaN), etc.

Normalisation

En prenant le nombre à virgule flottante 8,5 comme exemple, si vous souhaitez le changer au format IEEE 754, vous devez d'abord faire une certaine normalisation : diviser 8,5 en 8 + 0,5, soit 2^3 + (cfrac{1}{ 2}) ^1$, puis écrit en binaire, il devient , et enfin écrit sous la forme $1,0001 fois 2^3$, ce qui est très similaire à la notation scientifique décimale.

1000.1

Nombres à virgule flottante simple précision

Dans IEEE 754, les nombres à virgule flottante de 32 bits sont divisés en trois parties, à savoir le signe, l'exposant et la fraction, totalisant 32 bits

Une brève discussion sur les raisons pour lesquelles les opérations en virgule flottante produisent des erreurs Symbole numérique (signe) : le bit le plus à gauche représente le signe positif et négatif S'il est positif, le signe est 0, sinon c'est 1

    exposant : le bit du milieu représente la puissance après normalisation, en utilisant le format du
  • code valeur vraie + 127
  • , soit 3 plus 127 égale 130
  • Mantisse (fraction) : les 23 bits à l'extrême droite sont placés C'est la partie décimale En termes de , c'est le
  • . 1.00011. après avoir supprimé 0001 Donc si 8.5 est exprimé au format 32 bits, cela devrait ressembler à ceci :

Une brève discussion sur les raisons pour lesquelles les opérations en virgule flottante produisent des erreurs

Dans quelles circonstances des erreurs se produiront-elles ?

L'exemple de 8,5 mentionné ci-dessus peut être exprimé sous la forme $2^3 + (cfrac{1}{2})^1$ car 8 et 0,5 se trouvent être des puissances de 2, il n'y aura donc aucun problème de précision.

Mais s'il est 8,9, il n'y a aucun moyen d'ajouter des puissances de 2, il sera donc forcé d'être exprimé comme 1,0001110011 $... fois 2^3$, et il y aura également une erreur d'environ 0,0000003$ si vous. Si vous êtes curieux de connaître le résultat, vous pouvez accéder au site Web du convertisseur à virgule flottante IEEE-754 pour jouer.

Nombres à virgule flottante double précision

Les nombres à virgule flottante simple précision mentionnés précédemment n'utilisent que 32 bits pour les représenter Afin de réduire l'erreur, IEEE 754 définit également comment utiliser 64 bits. pour représenter des nombres à virgule flottante, ce qui équivaut à 32 bits, par rapport au bit, la partie fraction a plus que doublé, passant de 23 bits à 52 bits, la précision sera donc naturellement considérablement améliorée.

Une brève discussion sur les raisons pour lesquelles les opérations en virgule flottante produisent des erreurs

Prenons le 8,9 tout à l'heure comme exemple. Bien qu'il puisse être plus précis s'il est exprimé en 64 bits, car 8,9 ne peut pas être complètement écrit comme la somme des puissances de 2, il y aura toujours une erreur en atteignant 16 décimales. places Cependant, avec L'erreur simple précision de 0,0000003 est beaucoup plus petite que

Une brève discussion sur les raisons pour lesquelles les opérations en virgule flottante produisent des erreurs

Des situations similaires incluent 1.0 et 0.999...999 en Python sont égales, 123 et 122.999...999 sont également égales, car l'écart entre elles est trop petit pour être placé. Dans la fraction, chaque bit binaire est identique au format binaire.

Une brève discussion sur les raisons pour lesquelles les opérations en virgule flottante produisent des erreurs

Solution

Étant donné que l'erreur des nombres à virgule flottante est inévitable, nous devons vivre avec. Voici deux méthodes de traitement courantes :

Définir l'erreur maximale autorisée ε (epsilon)

Dans certaines langues, ce qu'on appelle epsilon est fourni pour vous permettre de juger s'il se situe dans la plage autorisée d'erreur en virgule flottante. En Python, la valeur de epsilon est d'environ $2,2e^{-16}$

Une brève discussion sur les raisons pour lesquelles les opérations en virgule flottante produisent des erreurs

Vous pouvez ainsi réécrire 0.1 + 0.2 == 0.3 en 0.1 + 0.2 — 0.3 , afin d'éviter que des erreurs en virgule flottante ne causent des problèmes pendant l'opération, et comparer correctement si 0,1 plus 0,2 est égal à 0,3.

Bien sûr, si le système ne le fournit pas, vous pouvez également définir vous-même un epsilon et le régler à environ 2 à la puissance -15

Entièrement en utilisant le système décimal

La raison pour laquelle il existe un L'erreur de virgule flottante est due au fait que pendant le processus de conversion de décimal en binaire, il n'y a aucun moyen de mettre toutes les parties décimales dans la mantisse. Puisqu'il peut y avoir des erreurs dans la conversion, nous ne convertissons tout simplement pas et n'utilisons pas de décimal pour effectuer les calculs. directement.

Il existe un module appelé decimal en Python, et il existe un package similaire en JavaScript. Il peut vous aider à effectuer des calculs en décimal, tout comme vous pouvez calculer 0,1 + 0,2 avec un stylo et du papier sans aucune erreur ni erreur.

Une brève discussion sur les raisons pour lesquelles les opérations en virgule flottante produisent des erreurs

Bien que l'utilisation de calculs décimaux puisse éviter complètement les erreurs dans les nombres à virgule flottante, car les calculs décimaux de Decimal sont simulés, les calculs binaires sont toujours utilisés dans le circuit CPU de niveau le plus bas et l'exécution sera plus lente que les calculs à virgule flottante natifs. Les opérations sur virgule sont beaucoup plus lentes, il n'est donc pas recommandé d'utiliser Decimal pour toutes les opérations sur virgule flottante.

Pour plus de connaissances sur la programmation, veuillez visiter : Introduction à la programmation ! !

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer