Ik ben benieuwd welke beter zou passen als valutaveld? Ik zal eenvoudige bewerkingen doen, zoals het nemen van verschil, het percentage tussen oude en nieuwe prijzen. Ik ben van plan om twee cijfers na de nul te behouden (dwz 10,50) en als deze cijfers nul zijn, zal ik deze cijfers verbergen en weergeven als “10”
ps: Valuta is NIET gebaseerd op dollars 🙂
Antwoord 1, autoriteit 100%
Gebruik altijd DecimalField
voor geld. Zelfs eenvoudige bewerkingen (optellen, aftrekken) zijn niet immuun voor problemen met zwevende afronding:
>>> 10.50 - 0.20
10.300000000000001
>>> Decimal('10.50') - Decimal('0.20')
Decimal('10.30')
Antwoord 2, autoriteit 48%
Het antwoord op de vraag is correct, maar sommige gebruikers zullen op deze vraag stuiten om het verschil te ontdekken tussen het DecimalField
en het FloatField
. Het vlotter-afrondingsprobleem dat Seth ter sprake brengt, is een probleem voor valuta.
De Django Docs-staten
De klasse
FloatField
wordt soms verward met de klasseDecimalField
. Hoewel ze allebei reële getallen vertegenwoordigen, vertegenwoordigen ze die getallen anders.FloatField
gebruikt hetfloat
-type van Python intern, terwijlDecimalField
hetDecimal
-type van Python gebruikt.
Lees hier.
Hier zijn andere verschillen tussen de twee velden:
Decimaalveld:
- DecimalFields moeten een
decimal_places
en eenmax_digits
-attribuut definiëren. - U krijgt hier twee gratis formuliervalidaties van de bovenstaande vereiste kenmerken, bijv. als u
max_digits
instelt op4
, en u typt een decimaalteken dat4.00000
(5 cijfers) is, krijgt u deze foutmelding: Zorg ervoor dat er zijn in totaal niet meer dan 4 cijfers. - Je krijgt ook een vergelijkbare vormvalidatie voor decimalen (die in de meeste browsers ook aan de voorkant valideert met behulp van het step-attribuut in het invoerveld. Als je
decimal_places = 1
instelt en typt in0.001
als de waarde krijgt u een foutmelding dat de minimumwaarde0.1
moet zijn. - Retourneert een
decimal.Decimal
, type is<class 'decimal.Decimal'>
- Heeft niet de extra validatie van
DecimalField
- Bij een
Decimal
type wordt er ook voor u afgerond vanwege de vereiste attributen die moeten worden ingesteld zoals hierboven beschreven. Dus uit de schaal, als je - In de database (postgresql) wordt het
DecimalField
opgeslagen als eennumeric(max_digits, decimal_places)
Type, en Storage is ingesteld als “main”, uit het bovenstaande voorbeeld het Type isnumeric(4,1)
Meer over DecimalField uit de Django-documenten.
FloatField:
- Retourneert het ingebouwde float-type,
<type 'float'>
- Geen slimme afronding en kan zelfs resulteren in afrondingsproblemen zoals beschreven in Seths antwoord.
- Heeft niet de extra formuliervalidatie die u krijgt van
DecimalField
- In de database (postgresql) wordt het
FloatField
opgeslagen als een “dubbele precisie” Type, en Opslag is ingesteld als “plain”
Meer over FloatField uit de Django-documenten.
Van toepassing op beide:
- Beide velden strekken zich uit van de klasse
Field
en kunnenblank
,null
,verbose_name
,name
,primary_key
,max_length
,unique
,db_index
,rel
,default
,editable
,serialize
,unique_for_date
,unique_for_month
,unique_for_year
,choices
,help_text
,db_column
,db_tablespace
,auto_created
,validators
,error_messages
attributen, zoals alle velden die uitField
komen, zouden hebben. - De standaard formulierwidget voor beide velden is een
TextInput
.
Ik kwam deze vraag tegen toen ik op zoek was naar het verschil tussen de twee velden, dus ik denk dat dit mensen in dezelfde situatie zal helpen 🙂
UPDATE: om de vraag te beantwoorden, ik denk dat je met beide kunt wegkomen om valuta weer te geven, hoewel Decimal
veel beter past. Er is een afrondingsprobleem wanneer het meetelt voor float’s, dus u moet round(value, 2)
gebruiken om uw float
-representatie afgerond op twee decimalen te houden. Hier is een snel voorbeeld:
>>> round(1.13 * 50 + .01, 2)
56.51
Je kunt nog steeds in de problemen komen met float
en round
. Zoals hier zien we dat het naar beneden wordt afgerond op een waarde van 5
:
>>> round(5.685, 2)
5.68
Maar in dit geval wordt het naar boven afgerond:
>>> round(2.995, 2)
3.0
Het heeft allemaal te maken met hoe de float in het geheugen wordt opgeslagen. Zie hier.
Antwoord 3, autoriteit 8%
Ik weet dat dit super oud is, maar ik kwam het tegen toen ik op zoek was naar iets heel anders, en ik wilde zeggen dat het in het algemeen niet raadzaam is om drijvende-kommagetallen (float ofdecimaal) te gebruiken ) voor valuta, aangezien wiskundige afronding met drijvende komma altijd zal leiden tot kleine rekenfouten die in de loop van de tijd tot zeer grote verschillen kunnen leiden.
Gebruik in plaats daarvan een geheel getal of een tekenreeks naar keuze. Vermenigvuldig uw valuta om de decimale plaats naar het einde te verplaatsen en maak een geheel getal wanneer u het opslaat, en verplaats dat decimaalteken vervolgens terug naar waar het hoort wanneer u het moet tonen. Dit is eigenlijk hoe banken (en de meeste valutabibliotheken) omgaan met het opslaan van gegevens en het zal u later veel problemen besparen.
Ik heb dit op de harde manier geleerd omdat het niet echt een algemeen onderwerp is; misschien voorkomt dit dat iemand anders hetzelfde doet.
Antwoord 4, autoriteit 5%
edit: het Satchmo-project is niet langer actief, dus bekijk deze alternatieven voor het omgaan met valuta
Het op Django gebaseerde Satchmo Projectheeft een CurrencyField en CurrencyWidget die het bekijken waard zijn.
Bekijk de satchmo_utils app-map voor de bron