Maison >développement back-end >Golang >Pourquoi un programme Go utilisant « float32 » entre-t-il dans une boucle infinie alors qu'un programme similaire utilisant « float64 » se termine, lorsque les deux accumulent 0,2 et soustraient 0,3 de manière itérative jusqu'à dépasser 1,0 ?

Pourquoi un programme Go utilisant « float32 » entre-t-il dans une boucle infinie alors qu'un programme similaire utilisant « float64 » se termine, lorsque les deux accumulent 0,2 et soustraient 0,3 de manière itérative jusqu'à dépasser 1,0 ?

Linda Hamilton
Linda Hamiltonoriginal
2024-12-07 18:21:15291parcourir

Why does a Go program using `float32` enter an infinite loop while a similar program using `float64` terminates, when both accumulate 0.2 and subtract 0.3 iteratively until exceeding 1.0?

Différences de précision à virgule flottante dans Go : float32 vs float64

Dans Go, les valeurs à virgule flottante peuvent être représentées par float32 ou float64 , avec différents niveaux de précision. Dans une expérience récente, un programme a démontré des erreurs en virgule flottante lors de l'utilisation des types float32 et float64.

Le programme accumule la valeur à virgule flottante 0,2 plusieurs fois, en soustrayant 0,3 à chaque itération jusqu'à ce que la valeur dépasse 1,0. Lors de l'utilisation de float64, le programme génère 1.000000e 00 après 54 itérations, similaire au comportement du même programme en C (lors de l'utilisation de double).

Cependant, lors de l'utilisation de float32 dans le programme Go, il entre dans un nombre infini boucle. Cette incohérence résulte des différentes façons dont Go et C gèrent les représentations float32.

Examen des représentations à virgule flottante

À l'aide des fonctions math.Float32bits et math.Float64bits, nous peut observer comment Go représente les valeurs décimales sous forme binaire IEEE 754 valeurs :

float32(0.1): 00111101110011001100110011001101
float32(0.2): 00111110010011001100110011001101
float32(0.3): 00111110100110011001100110011010
float64(0.1): 0011111110111001100110011001100110011001100110011001100110011010
float64(0.2): 0011111111001001100110011001100110011001100110011001100110011010
float64(0.3): 0011111111010011001100110011001100110011001100110011001100110011

Analyse de la précision float32

La conversion de ces valeurs binaires en décimales révèle que la valeur initiale de a dans le programme Go utilisant float32 devient :

0.20000000298023224
+ 0.10000000149011612
- 0.30000001192092896
= -7.4505806e-9

Cette valeur négative empêche la boucle d'atteindre 1.0.

Différences d'implémentation en C

En C, le comportement diffère en raison des différences dans la façon dont les constantes float sont gérées. Go se rapproche de 0,1 avec la représentation binaire la plus proche, tandis que C peut tronquer le dernier bit.

Go:   00111101110011001100110011001101 => 0.10000000149011612
C(?): 00111101110011001100110011001100 => 0.09999999403953552

En conséquence, C permet à 0,1 d'être représenté avec plus de précision, ce qui entraîne un résultat différent pour la boucle à virgule flottante. lors de l'utilisation de float32.

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:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn