När det räknar med heltal (int
), räknar Python exakt, om maskinens minne räcker till. Till exempel kan talet $2^{10000}$ beräknas med kommandot 2**10000
utan problem. Med decimaltal får man emellertid problem, eftersom till exempel $\sqrt{2}=1{,}4142...$ redan innehåller oändligt med decimaler och inte ryms i datorns ändliga minne.
Ett typiskt sätt att spara decimaltal på datorn är flyttal (eng. floating point number, float
). I ett flyttal kommer decimalkommat efter den första värdesiffran, dvs. till exempel skulle talet $12345$ betecknas som $$12345 = 1{,}2345\cdot 10^4.$$ Koefficienten $1{,}2345$ kallas mantissa. Datorns gränser kommer emot eftersom mantissan enbart har tillgång till ett begränsat antal siffror. Därför kan till exempel talet $$1/3 = 0{,}33333... = 3{,}3333...\cdot 10^{-1}$$ inte sparas exakt, utan det avrundas till närmaste tillgängliga tal. Därtill används enbart exponenter av begränsad storlek, så godtyckligt stora tal kan inte presenteras.
I själva verket sparar Python talen som binära tal. Det finns 53 värdesiffror i det binära talsystemet, vilket innebär att det finns cirka $15$ värdesiffror i det decimala talsystemet. Den största möjliga koefficienten är $2^{2023}$ och den minsta är $2^{-2022}$. Härav följer att endast de tal vars presentation som binära tal är ändlig sparas exakt. Till exempel är den binära talrepresentationen hos decimalsystemets tal $0,2$ oändlig: $0{,}0011001100110011...$ När denna avrundas till $53$ värdesiffror i den binära talsystemet, är resultatet ett tal, som motsvarar talet $$0{,}20000000000000001110223024625156...$$ i decimalsystemet.
Det väsentliga i allt detta är alltså att när man räknar med decimaltal är alla decimaler från och med 16 värdesiffror helt opålitliga.
Mer information om flyttal i Python hittar du i Pythons dokumentation och Pythons flyttalsstandard i Wikipedia.
==
. Skriv ett program som matar ut sanningsvärdena för uttrycken
0.1 + 0.1 == 0.2
0.1 + 0.2 == 0.3
0.3 + 0.5 == 0.8
3*0.1 == 0.3
0.1 + 0.1 - 0.2
0.1 + 0.2 - 0.3
0.3 + 0.5 - 0.8
3*0.1 - 0.3
Skriv ditt program här:
==
. Ett bättre sätt att testa likheten hos talen $a$ och $b$ är att nöja sig med att kontrollera att $|a-b|$ är tillräckligt litet, där ”tillräckligt litet” betyder ”många storleksklasser mindre än det större av talen $|a|$ och $|b|$”.
Till exempel kan vi kontrollera om $x = 2{,}2360689774$ är ett bra närmevärde för talet $\sqrt{5}$ genom att kontrollera, om $\left|x-\sqrt{5}\right|<10^{-9}$ gäller. Gör en kod, som skriver ut Närmevärdet är korrekt!
eller Närmevärdet är fel!
i enlighet med om detta villkor uppfylls eller inte.
Kvadratroten fås med math
-paketets funktion math.sqrt
och absoluta värdet med funktionen abs
.
Skriv ditt program här:
10.0**50 + 1 - 10.0**50
resultatet 0. Orsaken är att $10^{50}+1 \approx 10^{50}$, om man inte använder 51 värdesiffror.
Skriv en kod som på raderna efter varandra skriver ut värdet för uttrycket 10.0**n+1-10.0**n
när $n = 1, 2, 3, \ldots, 20$. Kom ihåg att skriva 10.0
, inte 10
. Vad upptäcker du?
Skriv ditt program här:
Problemet beror på att $b^2$ är mycket större än $4ac$. Då gäller $$\sqrt{b^2-4ac} \approx \sqrt{b^2-0} = |b|.$$ När värdesiffrorna tar slut kan närmevärdet för talen $\sqrt{b^2-4ac}$ och $b$ alltså vara samma! Lösningsformeln slutar i formen $$x_1\approx \frac{-b + |b|}{2a} \quad \text{och} \quad x_2\approx \frac{-b - |b|}{2a},$$ varpå man får $x_1\approx 0$ med de positiva talen $b$ och motsvarande får man $x_2 \approx 0$ med det negativa talet $b$, och inga värdetal är korrekta i svaret. Subtraktion är farligt!
Koden ska även fungera för ekvationer där $b^2$ är mycket större än $4ac$, till exempel den tidigare presenterade ekvationen $3x^2+10^{20}x+5=0$ samt ekvationen $3x^2-10^{20}x+5=0$.
Om du vill kan du även kontrollera om det över huvud taget finns reella lösningar.
Denna uppgift bedöms inte automatiskt.
Skriv ditt program här: