Python, een veelgebruikte programmeertaal, blinkt uit in numerieke computertaken, maar is toch niet immuun voor de uitdagingen die drijvende-kommaberekeningen met zich meebrengen. Getallen met drijvende komma in Python zijn benaderingen van reële getallen, wat leidt tot afrondingsfouten, verlies van nauwkeurigheid en annuleringen dat berekeningen in de war kan sturen. We kunnen Ontdek deze fouten door naar vreemde resultaten te zoeken en het gebruik van hulpmiddelennumpy.finfo>naar precisie bewaken . Met wat voorzichtigheid en slimme trucjes kunnen we dat wel houd deze fouten onder controle en ervoor te zorgen dat onze Python-berekeningen betrouwbaar zijn. In dit artikel zullen we de fijne kneepjes van drijvende-kommafouten onderzoeken Python .
Wat zijn drijvende-kommagetallen?
Drijvende-kommagetallen zijn een efficiënte manier om reële getallen in computers weer te geven. Ze bestaan uit drie delen:
- Significant: De daadwerkelijke cijfers die het nummer vertegenwoordigen (bijvoorbeeld 3.14159)
- Exponent: Geeft aan op hoeveel plaatsen de significantie naar links of rechts moet worden verschoven (bijvoorbeeld -2 in 3,14159 x 10^-2)
- Baseren: Meestal 2 voor computers, die bepalen hoe getallen intern worden weergegeven
Waarom treden drijvende-kommafouten op?
Drijvende-kommafouten ontstaan doordat computers reële getallen opslaan met behulp van een eindig aantal bits, wat leidt tot benaderingen en potentiële onnauwkeurigheden. Drijvende-kommagetallen hebben intrinsieke beperkingen:
- Eindige precisie: Er kan slechts een beperkt aantal cijfers in de significantie worden opgeslagen, wat leidt tot afrondingsfouten bij het weergeven van exacte decimalen.
- Verlies van precisie: Bewerkingen zoals optellen of aftrekken kunnen de nauwkeurigheid verder verminderen, waardoor de effecten van afronding nog groter worden.
- Onderloop/overloop: Extreem kleine of grote getallen kunnen buiten het representatieve bereik vallen, wat kan leiden tot onderstroom (wordt nul) of overloop (wordt oneindig).
Soorten drijvende-kommafouten
a) Afrondingsfouten: De meest voorkomende komt voor wanneer een exacte decimaal moet worden benaderd om te passen bij de beperkte precisie van een vlotter.
b) Verlies van precisie: Bij daaropvolgende bewerkingen kunnen zich geleidelijk afrondingsfouten voordoen, wat tot aanzienlijke onnauwkeurigheden in het eindresultaat kan leiden.
c) Catastrofale annulering: Bij het aftrekken van bijna gelijke getallen met tegengestelde tekens vallen de significante cijfers weg, waardoor een klein en onnauwkeurig resultaat overblijft.
d) Overloop/onderloop: Deze komen voor wanneer berekeningen het representatieve bereik van float-waarden overschrijden, wat leidt tot onnauwkeurige of betekenisloze resultaten.
Drijvende-kommafouten detecteren
- Onverwachte resultaten waarnemen: Het vergelijken van berekende waarden met verwachte uitkomsten of het visualiseren van gegevens kan inconsistenties aan het licht brengen die vaak door fouten worden veroorzaakt.
- Met behulp van bibliotheken zoals
numpy.finfo>: Bibliotheken zoalsnumpy>hulpmiddelen bieden zoalsfinfo>om de nauwkeurigheid en beperkingen van verschillende float-gegevenstypen te controleren.
Python drijvende-kommafout
Hier zullen we verschillende soorten voorbeelden bespreken die drijvende-kommafouten in Python illustreren:
Verlies van precisie bij decimale naar binaire conversie
In dit voorbeeld wordt het decimale getal 0,1 omgezet naar binair. Vanwege de oneindige binaire expansie van 0,1 wordt slechts een eindig aantal bits gebruikt, wat leidt tot verlies aan precisie.
Python3
decimal_number>=> 0.1> binary_representation>=> format>(decimal_number,>'.30f'>)># 30 decimal places> print>(f>'Decimal: {decimal_number}
Binary: {binary_representation}'>)> |
>
>
Uitgang:
Decimal: 0.1 Binary: 0.100000000000000005551115123126>
Afrondingsfouten
Hier wordt verwacht dat het resultaat van de optelling van 1/3 driemaal 1,0 is. Als gevolg van afrondingsfouten bij het weergeven van 1/3 is de som echter mogelijk niet precies 1,0.
Python3
result>=> 1.0> /> 3.0> sum_result>=> result>+> result>+> result> print>(f>'Expected Result: 1.0
Actual Result: {sum_result}'>)> |
>
>
Uitgang:
Expected Result: 1.0 Actual Result: 1.0>
Accumulatieve fouten in iteratieve berekeningen
Dit voorbeeld laat zien hoe accumulatieve fouten kunnen optreden in iteratieve berekeningen. Het tien keer optellen van 0,1 levert mogelijk geen exact resultaat van 1,0 op vanwege beperkingen van de drijvende-kommaprecisie.
Python3
total>=> 0.0> for> i>in> range>(>10>):> >total>+>=> 0.1> print>(f>'Expected Result: 1.0
Actual Result: {total}'>)> |
>
>
Uitgang:
Expected Result: 1.0 Actual Result: 0.9999999999999999>
Vergelijkingsproblemen
In dit geval levert het vergelijken van de som van 0,1 en 0,2 met 0,3 mogelijk niet het verwachte resultaat opTrue>resultaat als gevolg van de inherente onnauwkeurigheid van getallen met drijvende komma.
Python3
a>=> 0.1> +> 0.2> b>=> 0.3> print>(f>'a: {a}
b: {b}
Equal: {a == b}'>)> |
>
>
Uitgang:
a: 0.30000000000000004 b: 0.3 Equal: False>
Onverwachte resultaten in berekeningen
Hier, het aftrekken van1e16>van de som(1e16 + 1)>zal naar verwachting 1 opleveren, maar als gevolg van drijvende-kommafouten is het resultaat mogelijk niet precies 1.
Python3
a>=> 0.1> +> 0.2> b>=> 0.3> print>(f>'a: {a}
b: {b}
Equal: {a == b}'>)> |
>
>
Uitgang:
Expected Result: 1 Actual Result: 0.0>
Inzicht in drijvende-kommaprecisie
Hier zullen we de drijvende-kommaprecisie begrijpen: de 1,2 – 1,0 anomalie in Python-
Representatieve uitdagingen
Zoals bekend is, is 1,2 – 1,0 = 0,2. Maar als je hetzelfde probeert te doen in Python, zul je verrast zijn door de resultaten:
>>> 1,2 - 1,0>
Uitgang:
0.199999999999999996>
Dit kan worden beschouwd als een bug in Python, maar dat is het niet. Dit heeft weinig te maken met Python en veel meer met de manier waarop het onderliggende platform met drijvende-kommagetallen omgaat. Het is een normaal geval dat men tegenkomt bij het intern verwerken van drijvende-kommagetallen in een systeem. Het is een probleem dat wordt veroorzaakt bij de interne representatie van getallen met drijvende komma, waarbij een vast aantal binaire cijfers wordt gebruikt om een decimaal getal weer te geven. Het is moeilijk om sommige decimale getallen binair weer te geven, dus in veel gevallen leidt dit tot kleine afrondingsfouten. We kennen vergelijkbare gevallen in decimale wiskunde, veel resultaten kunnen niet worden weergegeven met een vast aantal decimale cijfers, bijvoorbeeld Voorbeeld
10 / 3 = 3.33333333.......>
In dit geval, als we 1,2 als voorbeeld nemen, is de representatie van 0,2 in binair getal 0,00110011001100110011001100…… enzovoort. Het is moeilijk om dit oneindige decimale getal intern op te slaan. Normaal gesproken wordt de waarde van een float-object opgeslagen in binaire drijvende komma met een vaste precisie ( doorgaans 53 bits ). Wij vertegenwoordigen dus 1.2 intern als,
1.0011001100110011001100110011001100110011001100110011>
Wat precies gelijk is aan:
1.1999999999999999555910790149937383830547332763671875>
Omgaan met drijvende-kommafouten
Hier zullen we verschillende voorbeelden bespreken van hoe om te gaan met drijvende-kommafouten in Python:
werkbalk voor snelle toegang tot woorden
Afronding op een specifiek decimaal
Door het resultaat af te ronden op een specifiek decimaal (bijvoorbeeld 2), kunt u de impact van kleine drijvende-kommafouten beperken.
Python3
result>=> 1.2> -> 1.0> rounded_result>=> round>(result,>2>)> print>(f>'Original Result: {result}
Rounded Result: {rounded_result}'>)> |
>
>
Uitgang:
Original Result: 0.19999999999999996 Rounded Result: 0.2>
Decimale klasse gebruiken voor hoge precisie
Dedecimal>module biedt deDecimal>klasse, waardoor rekenkunde met hogere nauwkeurigheid mogelijk is. De nauwkeurigheid instellen metgetcontext().prec>kan helpen bij het beheren van de nauwkeurigheid voor specifieke berekeningen
Python3
from> decimal>import> Decimal, getcontext> getcontext().prec>=> 4> # Set precision to 4 decimal places> result>=> Decimal(>'1.2'>)>-> Decimal(>'1.0'>)> print>(f>'High Precision Result: {result}'>)> |
>
>
Uitgang:
High Precision Result: 0.2>
Breuken gebruiken voor exacte weergaven
Defractions>module maakt het mogelijk om met exacte fractionele representaties te werken, waardoor drijvende-kommafouten worden vermeden.
Python3
from> fractions>import> Fraction> result>=> Fraction(>'1.2'>)>-> Fraction(>'1.0'>)> print>(f>'Exact Fractional Result: {result}'>)> |
>
>
Uitgang:
Exact Fractional Result: 1/5>
Tussenresultaten verwerken met decimalen
Gebruik deDecimal>klasse voor tussentijdse berekeningen om cumulatieve fouten te minimaliseren voordat deze weer naar float worden geconverteerd.
Python3
from> decimal>import> Decimal, getcontext> getcontext().prec>=> 6> # Set precision to 6 decimal places> intermediate_result>=> Decimal(>'1.2'>)>-> Decimal(>'1.0'>)> final_result>=> float>(intermediate_result)># Convert back to float if needed> print>(f>'Intermediate Result: {intermediate_result}
Final Result: {final_result}'>)> |
>
>
Uitgang:
Intermediate Result: 0.2 Final Result: 0.2>
Conclusie
Toch denk je waarom Python lost dit probleem niet op , eigenlijk heeft het niets met Python te maken. Het gebeurt omdat dit de manier is waarop het onderliggende c-platform met getallen met drijvende komma omgaat en uiteindelijk, vanwege de onnauwkeurigheid, zullen we getallen altijd hebben opgeschreven als een reeks van een vast aantal cijfers. Merk op dat dit in de aard van binaire drijvende komma ligt: dit is ook geen bug Python of C , en het is ook geen bug in je code. Je zult hetzelfde soort gedrag zien in alle talen die de drijvende-kommaberekeningen van onze hardware ondersteunen, hoewel sommige talen het verschil niet standaard of in alle uitvoermodi weergeven). We moeten met dit gedrag rekening houden als we ons bezighouden met wiskundige problemen met exacte precisie of als we deze gebruiken in voorwaardelijke uitspraken. Rekening drijvende punt sectie in Python-documentatie voor meer van dergelijke gedragingen.
Veelgestelde vragen (FAQ's)
1. Wat is een drijvende-kommafout in Python?
Een drijvende-kommafout in Python verwijst naar discrepanties tussen de verwachte en werkelijke resultaten bij het werken met drijvende-kommagetallen, die voortkomen uit de beperkingen van het weergeven van reële getallen in een binair systeem.
2. Waarom doet 1.2 - 1.0> niet gelijk 0.2> in Python?
Het verschil is te wijten aan de inherente uitdagingen bij het weergeven van decimale getallen in binair getal. Afrondingsfouten treden op tijdens de interne binaire representatie, wat tot onverwachte resultaten leidt.
3. Is de drijvende-kommafout een bug in Python?
Nee, het is geen bug in Python. Het is een veelvoorkomend probleem in de computerwereld, gerelateerd aan de manier waarop getallen met drijvende komma intern worden weergegeven. Python houdt zich aan de IEEE 754-standaard voor drijvende-kommaberekeningen.
4. Hoe kan ik een resultaat met drijvende komma afronden op een specifiek decimaal?
U kunt gebruik maken van de
round()>functie om een resultaat met drijvende komma af te ronden op een specifiek decimaal. Bijvoorbeeld,rounded_result = round(result, 2)>.
5. Wat is de decimal> module, en hoe helpt het bij het omgaan met drijvende-kommafouten?
De
decimal>module biedt deDecimal>klasse voor hogere precisie rekenkunde. De nauwkeurigheid instellen en gebruikenDecimal>kan drijvende-kommafouten helpen verminderen.