L'emballage et le Déballage binaire flotteur en python
Je vais avoir quelques problèmes avec l'emballage et le déballage de binaire flotteurs en python quand vous faites un fichier binaire en écriture. Voici ce que j'ai fait:
import struct
f = open('file.bin', 'wb')
value = 1.23456
data = struct.pack('f',value)
f.write(data)
f.close()
f = open('file.bin', 'rb')
print struct.unpack('f',f.read(4))
f.close()
Le résultat que j'obtiens est le suivant:
(1.2345600128173828,)
Ce qui se passe avec les chiffres supplémentaires? Est-ce une erreur d'arrondi? Comment cela fonctionne?
Oui, les nombres à virgule flottante sont, de par leur nature, sont imprécis.
Pour le pourquoi, voir Ce que Tout informaticien Devez Savoir à Propos de l'Arithmétique à virgule Flottante.
Le tutoriel Python résume la représentation des problèmes que vous avez rencontré.
Si vous voulez éviter de perdre de précision, vous pouvez pickle Décimal à la place.
Pour le pourquoi, voir Ce que Tout informaticien Devez Savoir à Propos de l'Arithmétique à virgule Flottante.
Le tutoriel Python résume la représentation des problèmes que vous avez rencontré.
Si vous voulez éviter de perdre de précision, vous pouvez pickle Décimal à la place.
OriginalL'auteur Wilsonator | 2013-04-23
Vous devez vous connecter pour publier un commentaire.
Sur la plupart des plates-formes, Python flotteurs sont ce que C pourrait appeler un
double
, mais vous avez écrit vos données commefloat
au lieu de cela, ce qui est la moitié de la précision.Si vous utilisez
double
, vous auriez moins de la perte de précision due:La
float
struct format offre seulement simple précision (24 bits pour la précision).Aussi je suppose que "(1.2345600128173828,)" est juste le python de la fonction d'impression en faisant preuve de plus de précision que le type de données?
0.8388607
, où avez-vous ce nombre? La fonction d'impression n'est pas faire preuve de "plus de précision", c'est juste la conversion de la valeur réelle qui est stocké en base dix.2^23 = 8388608 est ce que j'ai fait
Pas de. Fondamentalement, vous avez <=24 termes que vous pouvez ajouter ou de supprimer de: 1, 1/2, 1/4, 1/8, 1/16 etc, alors vous multipliez la somme par une puissance de deux dans l'intervalle -2^-126 à 2^127.
OriginalL'auteur Martijn Pieters
C'est un décimal à binaire problème.
Vous savez comment certaines fractions en décimales sont le répéter? Par exemple, 1/3 est 0.3333333-> pour toujours. 1/7 est 0.142857142857[142857]-> pour toujours.
Donc voici le kicker: répéter les fractions sont ceux avec un dénominateur qui a un facteur qui n'est pas un facteur de 10 -- par exemple pas un multiple de 2 et/ou 5.
Alors maintenant, comment cela fonctionne en binaire? Eh bien, elle suce plutôt, parce que le seul facteur qui répartit uniformément est 2. Tous les autres nombres premiers en plus de 2 devra répéter les décimales qui se répète indéfiniment -- et qui comprend des dixièmes, centièmes, etc, qui tous ont un facteur de 5 dans le dénominateur. 1.2345 est 12345/10000, qui contient des facteurs 2 et 5 dans le dénominateur, et que 5 signifie que vous avez une répétition de décimal en binaire qui se répète jamais.
Mais vous ne pouvez pas répéter éternellement. Ce qui signifie que vous aurez à arrondir les décimales en vue de l'installation dans les chiffres binaires codant pour votre flotteur.
Lorsque vous convertissez retour à la virgule, l'erreur d'arrondi est révélé.
Le résultat pour le codage est: calculer les divisions de que le plus tard possible de garder ces erreurs de s'accumuler à chaque calcul.
OriginalL'auteur Kiki Jewell