2017-09-13 2 views
1
worth = Decimal(request.POST.get('worth')) 
print(request.user.profile.cash) # -> prints 10000.000000000000000 
print(worth) # -> prints 10000 
Profile.objects.filter(user=request.user).update(cash=F('cash')-worth) 
request.user.profile.refresh_from_db() 
if request.user.profile.cash < 0: 
    ###!!!!#### 
    print(request.user.profile.cash) # -> -1.819E-12 

#model definition: 
class Profile(models.Model): 
    cash = models.DecimalField(default=10000, max_digits=30, decimal_places=15) 

comme on peut le voir, le joueur a 10k comptant et je soustrais 10k, ce qui entraîne des valeurs négatives, comment puis-je résoudre ce problème? Je ne permets pas que l'argent soit négatif comme on peut s'y attendre. Est-ce que je fais quelque chose qui ne va pas?Django perte de précision décimale

Je veux que le joueur puisse aller all-in avec son argent.

+0

Qu'est-ce que 'user.profile.cash'? –

+0

Peut-être que l'expression 'F()' convertit implicitement la décimale en un nombre à virgule flottante? La valeur '-1.1819E-12' est un nombre à virgule flottante. –

+0

Quel backend de base de données utilisez-vous? Cela peut être un problème spécifique à la base de données. Par exemple, SQLlite n'a pas de champ décimal natif. Django doit utiliser une solution de contournement. –

Répondre

1

Vous pouvez résoudre ce problème en faisant la soustraction de la valeur de l'argent en python (c'est-à-dire pas avec une requête de base de données). Je suis sûr que vous auriez d'abord besoin de convertir la valeur Decimal pour cela. La raison pour laquelle cela pourrait fonctionner est que Django utilise les valeurs Decimal du module decimal pour faire de l'arithmétique avec des valeurs de champs décimaux qui ont une précision parfaite pour les nombres décimaux. Je ne suis pas sûr de ce que fait votre base de données lorsque vous faites cette requête, mais cela doit impliquer une sorte de calcul en virgule flottante. La valeur que vous voyez est fondamentalement équivalente à zéro (-0.000000000001819) mais avec une erreur de virgule flottante incluse.