Python, et udbredt programmeringssprog, udmærker sig i numeriske computeropgaver, men det er ikke immunt over for de udfordringer, som floating-point aritmetik udgør. Flydende kommatal i Python er tilnærmelser af reelle tal, der fører til afrundingsfejl, tab af præcision og annulleringer der kan afsløre beregninger. Vi kan få øje på disse fejl ved at lede efter mærkelige resultater og bruge værktøjernumpy.finfo>til overvåge præcision . Med lidt forsigtighed og smarte tricks kan vi holde disse fejl under kontrol og sikre, at vores Python-beregninger er pålidelige. I denne artikel vil vi udforske forviklingerne af floating-point fejl i Python .
Hvad er floating point-tal?
Flydende kommatal er en effektiv måde at repræsentere reelle tal på i computere. De består af tre dele:
- Væsentlig: De faktiske cifre, der repræsenterer nummeret (f.eks. 3,14159)
- Eksponent: Fortæller, hvor mange steder signifikanden skal flyttes til venstre eller højre (f.eks. -2 i 3,14159 x 10^-2)
- Grundlag: Typisk 2 for computere, der bestemmer, hvordan tal repræsenteres internt
Hvorfor opstår der floating-point fejl?
Flydende kommafejl opstår, fordi computere gemmer reelle tal ved hjælp af et begrænset antal bits, hvilket fører til tilnærmelser og potentielle unøjagtigheder. Flydende kommatal har iboende begrænsninger:
- Endelig præcision: Kun et begrænset antal cifre kan gemmes i signifikanden, hvilket fører til afrundingsfejl når de repræsenterer nøjagtige decimaler.
- Tab af præcision: Operationer som addition eller subtraktion kan yderligere reducere præcisionen og forstærke virkningerne af afrunding.
- Underløb/Overløb: Ekstremt små eller store tal kan falde uden for det repræsentative område, hvilket fører til underløb (bliver nul) eller flyde over (bliver uendelig).
Typer af flydende point-fejl
a) Afrundingsfejl: Den mest almindelige forekommer, når en nøjagtig decimal skal tilnærmes for at passe til den begrænsede præcision af en flyder.
b) Tab af præcision: Efterfølgende operationer kan gradvist akkumulere afrundingsfejl, hvilket fører til betydelige unøjagtigheder i det endelige resultat.
c) Katastrofal aflysning: Når man trækker næsten lige store tal fra med modsatte fortegn, ophæves deres signifikante cifre, hvilket efterlader et lille og unøjagtigt resultat.
d) Overløb/Underløb: Disse opstår, når beregninger overstiger det repræsentative interval af flydende værdier, hvilket fører til unøjagtige eller meningsløse resultater.
Registrering af flydende point-fejl
- Observerer uventede resultater: Sammenligning af beregnede værdier med forventede resultater eller visualisering af data kan afsløre uoverensstemmelser, der ofte er forårsaget af fejl.
- Brug af biblioteker som
numpy.finfo>: Biblioteker somnumpy>give værktøjer somfinfo>at kontrollere præcisionen og begrænsningerne af forskellige flydende datatyper.
Python-floating point-fejl
Her vil vi diskutere forskellige typer eksempler, der illustrerer floating-point fejl i Python:
Tab af præcision i decimal til binær konvertering
I dette eksempel konverteres decimaltallet 0,1 til binært. På grund af den uendelige binære udvidelse på 0,1 bruges kun et begrænset antal bits, hvilket fører til et tab af præcision.
Python3
decimal_number>=> 0.1> binary_representation>=> format>(decimal_number,>'.30f'>)># 30 decimal places> print>(f>'Decimal: {decimal_number}
Binary: {binary_representation}'>)> |
>
>
Produktion:
Decimal: 0.1 Binary: 0.100000000000000005551115123126>
Afrundingsfejl
Her forventes resultatet af tilføjelsen af 1/3 tre gange at blive 1,0. Men på grund af afrundingsfejl ved at repræsentere 1/3, er summen muligvis ikke nøjagtigt 1,0.
Python3
blokere YouTube-annoncer på Android
result>=> 1.0> /> 3.0> sum_result>=> result>+> result>+> result> print>(f>'Expected Result: 1.0
Actual Result: {sum_result}'>)> |
>
>
Produktion:
Expected Result: 1.0 Actual Result: 1.0>
Akkumulative fejl i iterative beregninger
Dette eksempel viser, hvordan akkumulerende fejl kan opstå i iterative beregninger. Tilføjelse af 0,1 ti gange giver muligvis ikke et nøjagtigt resultat på 1,0 på grund af floating-point-præcisionsbegrænsninger.
Python3
total>=> 0.0> for> i>in> range>(>10>):> >total>+>=> 0.1> print>(f>'Expected Result: 1.0
Actual Result: {total}'>)> |
>
>
Produktion:
Expected Result: 1.0 Actual Result: 0.9999999999999999>
Sammenligningsproblemer
I dette tilfælde vil en sammenligning af summen af 0,1 og 0,2 til 0,3 muligvis ikke give det forventedeTrue>resultat på grund af den iboende unøjagtighed af flydende kommatal.
Python3
a>=> 0.1> +> 0.2> b>=> 0.3> print>(f>'a: {a}
b: {b}
Equal: {a == b}'>)> |
>
>
Produktion:
a: 0.30000000000000004 b: 0.3 Equal: False>
Uventede resultater i beregninger
Her er subtraktionen af1e16>fra summen(1e16 + 1)>forventes at give 1, men på grund af floating-point-fejl er resultatet muligvis ikke nøjagtigt 1.
Python3
java switch erklæring
a>=> 0.1> +> 0.2> b>=> 0.3> print>(f>'a: {a}
b: {b}
Equal: {a == b}'>)> |
>
>
Produktion:
Expected Result: 1 Actual Result: 0.0>
Forståelse af flydende punktpræcision
Her vil vi forstå floating point-præcisionen: 1.2 – 1.0 Anomaly i Python-
Repræsentationsudfordringer
Som det er kendt, at 1,2 – 1,0 = 0,2. Men når du prøver at gøre det samme i Python, vil du blive overrasket over resultaterne:
>>> 1,2 - 1,0>
Produktion:
0.199999999999999996>
Dette kan betragtes som en fejl i Python, men det er det ikke. Dette har lidt at gøre med Python og meget mere at gøre med, hvordan den underliggende platform håndterer flydende kommatal. Det er et normalt tilfælde, man støder på, når man håndterer flydende kommanumre internt i et system. Det er et problem, der opstår, når den interne repræsentation af flydende kommatal, som bruger et fast antal binære cifre til at repræsentere et decimaltal. Det er svært at repræsentere nogle decimaltal i binær, så i mange tilfælde fører det til små afrundingsfejl. Vi kender lignende tilfælde i decimal matematik, mange resultater kan ikke repræsenteres med et fast antal decimaler, for Eksempel
10 / 3 = 3.33333333.......>
I dette tilfælde, med 1,2 som eksempel, er repræsentationen af 0,2 i binær 0,00110011001100110011001100…… og så videre. Det er svært at gemme dette uendelige decimaltal internt. Normalt lagres et flydende objekts værdi i binært flydende komma med en fast præcision ( typisk 53 bit ). Så vi repræsenterer 1.2 internt som,
1.0011001100110011001100110011001100110011001100110011>
Hvilket er nøjagtigt lig med:
1.1999999999999999555910790149937383830547332763671875>
Håndtering af flydende point-fejl
Her vil vi diskutere forskellige eksempler på, hvordan man håndterer flydende komma-fejl i Python:
Afrunding til en bestemt decimal
Ved at afrunde resultatet til en bestemt decimal (f.eks. 2), kan du afbøde virkningen af små floating-point fejl.
Python3
result>=> 1.2> -> 1.0> rounded_result>=> round>(result,>2>)> print>(f>'Original Result: {result}
Rounded Result: {rounded_result}'>)> |
>
>
Produktion:
Original Result: 0.19999999999999996 Rounded Result: 0.2>
Brug af decimalklasse for høj præcision
Detdecimal>modul giverDecimal>klasse, hvilket giver mulighed for aritmetik med højere præcision. Indstilling af præcisionen medgetcontext().prec>kan hjælpe med at styre præcision til specifikke beregninger
Python3
latex tekststørrelse
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}'>)> |
>
>
Produktion:
High Precision Result: 0.2>
Brug af brøker til nøjagtige repræsentationer
Detfractions>modul gør det muligt at arbejde med nøjagtige brøkrepræsentationer og undgå floating-point-fejl.
Python3
from> fractions>import> Fraction> result>=> Fraction(>'1.2'>)>-> Fraction(>'1.0'>)> print>(f>'Exact Fractional Result: {result}'>)> |
>
>
Produktion:
Exact Fractional Result: 1/5>
Håndtering af mellemresultater med decimaler
BrugDecimal>klasse for mellemliggende beregninger for at minimere kumulative fejl før konvertering tilbage til float.
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}'>)> |
>
>
Produktion:
Intermediate Result: 0.2 Final Result: 0.2>
Konklusion
Alligevel tænker du hvorfor python løser ikke dette problem , faktisk har det intet at gøre med python. Det sker, fordi det er den måde, den underliggende c-platform håndterer tal med flydende komma, og i sidste ende med unøjagtigheden har vi altid skrevet tal ned som en streng med et fast antal cifre. Bemærk, at dette er i selve naturen af binært flydende komma: dette er heller ikke en fejl i Python eller C , og det er heller ikke en fejl i din kode. Du vil se den samme slags adfærd på alle sprog, der understøtter vores hardwares flydende komma-aritmetik, selvom nogle sprog muligvis ikke viser forskellen som standard eller i alle outputtilstande). Vi er nødt til at overveje denne adfærd, når vi bekymrer os om matematiske problemer med nøjagtige behov eller bruger det i betingede udsagn. Kontrollere flydende komma afsnittet i python-dokumentationen for flere sådanne adfærdsmønstre.
Ofte stillede spørgsmål (ofte stillede spørgsmål)
1. Hvad er en floating-point fejl i Python?
En floating-point-fejl i Python refererer til uoverensstemmelser mellem de forventede og faktiske resultater, når man arbejder med floating-point-tal, som skyldes begrænsningerne ved at repræsentere reelle tal i et binært-baseret system.
2. Hvorfor gør 1.2 - 1.0> ikke lige 0.2> i Python?
Uoverensstemmelsen skyldes de iboende udfordringer ved at repræsentere decimaltal i binært. Afrundingsfejl opstår under den interne binære repræsentation, hvilket fører til uventede resultater.
3. Er floating-point-fejlen en fejl i Python?
Nej, det er ikke en fejl i Python. Det er et almindeligt problem inden for computing relateret til, hvordan flydende kommatal er repræsenteret internt. Python overholder IEEE 754-standarden for floating-point aritmetik.
hvis ved rudyard kipling resumé
4. Hvordan kan jeg afrunde et resultat med flydende komma til en bestemt decimal?
Du kan bruge
round()>funktion til at afrunde et flydende kommaresultat til en bestemt decimal. For eksempel,rounded_result = round(result, 2)>.
5. Hvad er decimal> modul, og hvordan hjælper det med at håndtere floating-point fejl?
Det
decimal>modul giverDecimal>klasse for højere præcision aritmetik. Indstilling af præcision og brugDecimal>kan hjælpe med at afbøde floating-point fejl.