Sida 3 av 4

Re: Pyhton 10.1 + 10.2 = 20.29999

Postat: 10 juli 2022, 23:50:31
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.

Re: Pyhton 10.1 + 10.2 = 20.29999

Postat: 11 juli 2022, 00:08:04
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.

Re: Pyhton 10.1 + 10.2 = 20.29999

Postat: 11 juli 2022, 01:03:44
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.

Re: Pyhton 10.1 + 10.2 = 20.29999

Postat: 11 juli 2022, 09:30:56
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.)

Re: Pyhton 10.1 + 10.2 = 20.29999

Postat: 11 juli 2022, 10:04:58
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?

Re: Pyhton 10.1 + 10.2 = 20.29999

Postat: 7 september 2022, 20:00:38
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

Re: Pyhton 10.1 + 10.2 = 20.29999

Postat: 8 september 2022, 21:11:39
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.

Re: Pyhton 10.1 + 10.2 = 20.29999

Postat: 4 september 2023, 20:08:46
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?

Re: Pyhton 10.1 + 10.2 = 20.29999

Postat: 5 september 2023, 18:08:46
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.

Re: Pyhton 10.1 + 10.2 = 20.29999

Postat: 6 september 2023, 08:30:50
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":-)

Re: Pyhton 10.1 + 10.2 = 20.29999

Postat: 6 september 2023, 09:29:05
av BJ
Intressant.

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

Menade du inte 0,1 i decimalform?

Re: Pyhton 10.1 + 10.2 = 20.29999

Postat: 6 september 2023, 09:50:21
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!

Re: Pyhton 10.1 + 10.2 = 20.29999

Postat: 6 september 2023, 09:53:32
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).

Re: Pyhton 10.1 + 10.2 = 20.29999

Postat: 6 september 2023, 10:01:15
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.

Re: Pyhton 10.1 + 10.2 = 20.29999

Postat: 6 september 2023, 10:06:19
av BJ
guckrum:
Ja, så är det ju som det ska formuleras. Jag tänkte lite fel. :)