Pyhton 10.1 + 10.2 = 20.29999

C, C++, Pascal, Assembly, Raspberry, Java, Matlab, Python, BASIC, SQL, PHP, etc.
Användarvisningsbild
GeekJoan
Admin
Inlägg: 10642
Blev medlem: 26 maj 2003, 15:59:27
Ort: Solna

Re: Pyhton 10.1 + 10.2 = 20.29999

Inlägg av GeekJoan »

Känns fortfarande konstigt. Datorn borde kunna räkna/lagra decimalerna precis som vanliga int tal. Behöver ju bara hålla reda på när första siffran slår över och öka det innan decimalen med ett. Men jag är ju ingen matematiker.
Användarvisningsbild
sodjan
EF Sponsor
Inlägg: 43148
Blev medlem: 10 maj 2005, 16:29:20
Ort: Söderköping
Kontakt:

Re: Pyhton 10.1 + 10.2 = 20.29999

Inlägg av sodjan »

Det är klart att datorer kan fixa det! Det är inga som helst problem.
Men det är inte det som "float" är avsett för! Det borde vara tydligt nu...
"Float" prioriterar ett stort dynamiskt omfång framför exakthet.
Användarvisningsbild
mrfrenzy
Co Admin
Inlägg: 14818
Blev medlem: 16 april 2006, 17:04:10

Re: Pyhton 10.1 + 10.2 = 20.29999

Inlägg av mrfrenzy »

När man jobbar med flyttal i många mikroprocessorer och även i CAN-kommuikation så bestämmer man i förväg hur många decimaler som behövs och representerar talen som heltal.
Exempelvis blir 10,1 + 10,2:
10100 + 10200 = 20300

Sedan i slutet när alla beräkningar är klara gör man omvandlingen till flyttal eller bara en formatering.

Oftast kan man enkelt bestämma detta i förväg baserat på vad värdet ska användas till i slutänden, sedan lägger man på en nolla till och ser hur många bitar som behövs eller om man bara ska avrunda upp till U16 eller U32.
guckrum
Inlägg: 1669
Blev medlem: 19 juni 2012, 09:04:27
Ort: Lund

Re: Pyhton 10.1 + 10.2 = 20.29999

Inlägg av guckrum »

Talrepresentation är lite knepigt. Ett "vanligt int-tal" är väl, tänker jag mig, till exempel en 32-bitars int. En sådan kan representera alla heltal mellan noll och 2^32-1 om den är unsigned. Om den övre gränsen (drygt 4 miljarder) räcker för dig kan du ju till exempel multiplicera allt med 100 för att få två exakta decimaler, så betyder till exempel heltalet 314 exakt decimaltalet 3.14.

Om 32 bitar inte räcker får man ta fler. Skall man hantera godtyckligt stora tal måste man också koda in hur stor plats varje tal tar. Så gör till exempel Python

Kod: Markera allt

>>> 2**10000
1995063116880758384883742162683585083823496831886192454852008949852943883022194663191996168403619459789933112942320912427155649134941378111759378593209632395785 ... 2596709376  # ca 3000 decimala siffror
Det var heltalen. Problemet med "decimaler" å andra sidan är att det inte funkar att bara lägga till fler bitar. Det ofta "inte går jämt upp", dvs man får en "periodisk decimalutveckling", exempelvis 1/3 = 0.3333... Ett sådant tal är _omöjligt_ att representera exakt med en ändlig mängd bitar. Det går inte. Man måste göra på något annat sätt, tex spara täljare och nämnare var för sig, eller helt enkelt gilla läget och se till att man har tillräcklig upplösning för sin applikation och sedan avrunda.

IEEE floats är den lösning som sitter i många processorer och den ger ofta ett bra resultat för många applikationer. Men det är bra att känna till vilka begränsningar de har. Till exempel kan en summa av tal bli olika beroende på vilken ordning man adderar talen i. En bra programmerare känner till detta och tar höjd för begränsningarna. I många telekomapplikationer räknar man till exempel mest med logaritmer av tal för att få upplösningen att räcka till. Osv. Det finns inte en enkel snabb lösning som fungerar i alla tillämpningar.

(Och när vi är överens om hur tal skall representeras kommer vi kanske till hur man skall representera matriser, och då blir det ännu knepigare.)
Användarvisningsbild
Lennart Aspenryd
Tidigare Lasp
Inlägg: 12607
Blev medlem: 1 juli 2011, 19:09:09
Ort: Helsingborg

Re: Pyhton 10.1 + 10.2 = 20.29999

Inlägg av Lennart Aspenryd »

Så de politiker i en USA delstat som ville att Pi skulle avrundas till tre för att det skulle vara lättare för ungarna i skolan, var inte helt fel ute då!
Inte bara bits och nibble, utan språkets hantering gör väl sitt till?
bus
Inlägg: 27
Blev medlem: 21 november 2014, 08:41:37

Re: Pyhton 10.1 + 10.2 = 20.29999

Inlägg av bus »

float är bra till det mesta, men man får hålla koll på antalet värdesiffror och vara bredd att avrunda med hänsyn till dem på slutet. Men då och då råkar man ut för tillämpningar som kräver andra lösningar och då lyser Python med sin styrka genom att ha flera olika talsystem så som Fraction, Decimal och Complex.

Om du till exempel behöver summera tal med oändlig decimalutveckling som 1/3 ≈ 1.33333333333333333333 så kan du använda Fractions

from fractions import Fraction
a = Fraction(1, 3)
b = Fraction(2, 3)
print(a+b)
1

När det gäller trådskaparens exempel så kan man välja att räkna i 10-delar
c = Fraction(101, 10)
d = Fraction(102, 10)
print(c+d)
203/10
agehall
Inlägg: 418
Blev medlem: 12 augusti 2020, 19:27:54

Re: Pyhton 10.1 + 10.2 = 20.29999

Inlägg av agehall »

Jag hoppas verkligen att Python inte tycker att 1/3 == 1.333333333…. för isåfall är det riktigt trasigt. :D

Fraction är dock bara bra till bråktal (vad jag vet iallafall). Det är inte samma sak som oändlig decimalutveckling vilket är en ganska viktig skillnad.

Återigen - det är viktigt att ha förståelse för vad man gör när man skriver kod. En av de vanligaste fallgroparna är att man försöker använda flyttal för att representera exakta decimaltal (som tex valutor) och det fungerar helt enkelt inte för det är inte vad flyttal är till för.
Användarvisningsbild
GeekJoan
Admin
Inlägg: 10642
Blev medlem: 26 maj 2003, 15:59:27
Ort: Solna

Re: Pyhton 10.1 + 10.2 = 20.29999

Inlägg av GeekJoan »

Förlåt om jag tar upp det här igen, men jag har funderat på en grej.
Skulle det bli "mer" rätt om man satte nollor efter?
ex: 10.1000000000000000000000000000000000000000000000000000000000000000
eller skiter den i alla nollor och ser det som 10.1?
Om så är fallet skulle man kunna skriva 10.10...01 och sen avrunda till 10 decimaler?
agehall
Inlägg: 418
Blev medlem: 12 augusti 2020, 19:27:54

Re: Pyhton 10.1 + 10.2 = 20.29999

Inlägg av agehall »

Nej, fler 0:or hjälper inte. Detta är ett fundamentalt problem med flyttal som du inte kan komma runt utan att gå över till flyttal som har mer precision.

Datorer kan tyvärr inte räkna 100% rätt under godtyckliga förutsättningar. Du som operatör/utvecklare måste ta ansvar för vad du gör och se till att du håller dig inom vad din hårdvara kan göra eller så får du ta till något bibliotek som löser det åt dig.
guckrum
Inlägg: 1669
Blev medlem: 19 juni 2012, 09:04:27
Ort: Lund

Re: Pyhton 10.1 + 10.2 = 20.29999

Inlägg av guckrum »

Problemet är egentligen något annat, och det går inte att lösa med högre precision.

Tänk på bråktalen 1/2 och 1/3:

- 1/2 kan man i decimalform skriva som 0.5. Det är exakt.

- 1/3 blir på decimalform 0.3333... Treorna tar aldrig slut, för att få ett exakt resultat krävs oändligt med decimaler. Det går ju inte. Skall man skriva ut det blir det alltid en approimation: 1/3 är ungefär 0.333. Man får se til att ha tillräckligt med decimaler för att det skall räcka och kanske bli över för den applikation man har. Detta får man lära sig i grundskolan.

Så varför blir det så, och kan man veta vilka bråktal som kan skrivas exakt och vilka som har oändligt med decimaler?

Jodå, enkelt, det handlar om talbaser. Vi använder till vardags talbas 10, och när vi skriver 123.456 så menar vi 1*(10*10) + 2*10 + 3*1 + 4*(1/10) + 5*(1/10/10) + 6*(1/10/10/10). Siffrorna i ett tal bestämmer hur mycket av en viss tiopotens som skall adderas till talet.

- Talet 1/2 kan multipliceras uppe och nere med fem: 1/2 = (5*1)/(5*2) = 5/10 = 0.5. Exakt.

- Talet 1/3 kan vi inte multiplicera så att nämnaren blir en multipel av 10. 3 gånger vadsomhelst kan inte bli 10 eller 100 eller 1000 osv. 10 och 3 är relativt prima, som det heter.


Men nu handlade det om att skriva det decimala talet 0.1 i flyttal. Varför kan vi inte skriva 0.1 exakt i flyttal då, det är ju precis 1/10?

Det är för att flyttal lagras binärt, dvs i basen 2 istället för basen 10. Alla binära tal skrivs som summor av tvåpotenser, tex 101.11 = 1*(2*2) + 0*(2) + 1*1 + 1*(1/2) + 1*(1/2/2) (=5.75 decimalt)

Det visar sig att det finns ingen ändlig "binalutveckling för talet 0.1 binärt. 0.1 (decimalt) är ungefär 0.0001100110... osv binärt, med oändligt med "binaler". Omöjligt att skriva ut efter som siffrorna aldrig tar slut.

Så talet 0.1 i binärform har samma "problem" (egenskap) som 1/3 i decimalform. Vi måste avrunda. Och se till att vi har tillräckligt många siffror för att inte få fel i våra beräkningar.

Därför skall man, som agehall precis skrivit, alltid använda etablerade och debuggade bibliotek när man håller på med matte, ÄVEN om man "vet vad man gör":-)
BJ
Inlägg: 8185
Blev medlem: 11 april 2007, 08:14:53
Ort: En_stad

Re: Pyhton 10.1 + 10.2 = 20.29999

Inlägg av BJ »

Intressant.

Så talet 0.1 i binärform har samma "problem"...

Menade du inte 0,1 i decimalform?
guckrum
Inlägg: 1669
Blev medlem: 19 juni 2012, 09:04:27
Ort: Lund

Re: Pyhton 10.1 + 10.2 = 20.29999

Inlägg av guckrum »

:-) Jovisst, jag menar: det decimala talet 0.1 har samma "problem" [när det uttrycks i binärform]. Tack för påpekandet!
Användarvisningsbild
hcb
Moderator
Inlägg: 5739
Blev medlem: 23 februari 2007, 21:44:50
Skype: hcbecker
Ort: Lystrup / Uppsala
Kontakt:

Re: Pyhton 10.1 + 10.2 = 20.29999

Inlägg av hcb »

Nej, 1/10 decimalt går inte att uttrycka exakt i binär form, på samma sätt som 1/3 inte går att uttrycka exakt i decimalform (med 10 som bas).
GFEF
Inlägg: 2370
Blev medlem: 4 december 2004, 18:44:04

Re: Pyhton 10.1 + 10.2 = 20.29999

Inlägg av GFEF »

En sak som saknas i denna tråd är "Gällande siffror"

Är ingående tal angivet angivet med en decimal 10,1 och 10,2 kan svaret inte bli noggrannare än en decimal.

Oavsett hur många decimal siffror som datorn ger.

10.1 + 10.2 = 20.29999 skall därför avrundas till 20.3

Vid beräkningar med flyttal används fler decimaler internt än vad som visas utåt.

Min HP 11C räknedosa använder 14 decimaler internt men avrundas till 10 decimaler i svar.

Ger i flesta fall godtagbara svar men som vanligt "skräp in = skräp ut".

Vid beräkningar med väldigt stora tal ger vanliga data algoritmer ej godtagbara svar.

Finns data algoritmer med valfri noggrannhet på bekostnad av beräknings tid och program storlek.
BJ
Inlägg: 8185
Blev medlem: 11 april 2007, 08:14:53
Ort: En_stad

Re: Pyhton 10.1 + 10.2 = 20.29999

Inlägg av BJ »

guckrum:
Ja, så är det ju som det ska formuleras. Jag tänkte lite fel. :)
Skriv svar