Schrift
[thread]9080[/thread]

Kleines Rätsel

Leser: 1


<< |< 1 2 >| >> 15 Einträge, 2 Seiten
sid burn
 2007-06-11 12:38
#77431 #77431
User since
2006-03-29
1520 Artikel
BenutzerIn

user image
Folgender Code:
Code: (dl )
1
2
sidburn@sid:~$ perl -e 'print int(2.4/0.2), "\n"';
11


Jetzt die Frage, warum kommt da 11 anstatt 12 heraus? Zumindest weiß ich folgendes:

1) Die Lösung ist richtig
2) Es hat etwas mit der Fließkommadarstellung zu tun. 2.4 / 0.2 soll ein ganz klitze klein weniger als 12 ergeben.

Kann das ganze jemand "einfach" erklären warum das so ist? Vorallem warum Punkt 2 so ist? Für mich ist das mit meiner Mathematik so nicht erklärbar.\n\n

<!--EDIT|sid burn|1181551127-->
Nicht mehr aktiv. Bei Kontakt: ICQ: 404181669 E-Mail: perl@david-raab.de
pq
 2007-06-11 12:47
#77432 #77432
User since
2003-08-04
12208 Artikel
Admin1
[Homepage]
user image
auf 50 nachkommastellen berechnet ist 2.4/0.2 wegen der rundungsfehler:
11.99999999999999822364316059974953532218933105468750

ein einfaches print macht daraus 12, ein int() rundet immer ab. nun
weiss ich aber leider nicht genau, warum print aufrundet bzw. ab
wievielen stellen es das macht\n\n

<!--EDIT|pq|1181551673-->
Always code as if the guy who ends up maintaining your code will be a violent psychopath who knows where you live. -- Damian Conway in "Perl Best Practices"
lesen: Wiki:Wie frage ich & perlintro Wiki:brian's Leitfaden für jedes Perl-Problem
moritz
 2007-06-11 12:51
#77433 #77433
User since
2007-05-11
923 Artikel
HausmeisterIn
[Homepage]
user image
Das mit der Fließkommadarstellung stimmt:

Code: (dl )
1
2
perl -e 'printf "%.15f\n", 2.4/0.2'
11.999999999999998


Wenn 12 statt 11 herausbekommen willst, musst du mit
Code: (dl )
int(0.5+$irgendwas)
runden.

Welche Zahl wie dargestellt wird, sieht man so:

Code: (dl )
1
2
3
4
$ perl -e 'printf "%.20f\n", 2.4'
2.39999999999999991118
$ perl -e 'printf "%.20f\n", 0.2'
0.20000000000000001110
sid burn
 2007-06-11 13:57
#77434 #77434
User since
2006-03-29
1520 Artikel
BenutzerIn

user image
Hab mir euer gepostetes angeschaut, und versuche mir mal selber eine Erklärung zu geben wie es anscheind ist.

Also Fließkommazahlen haben ja indem Sinne eine unendlich Tiefe. Wenn man 0.2 Schreibt dann könnte man dort praktischerweise noch unendlich Nullen anhängen.

Aber genau das lässt sich ja mit einem Computer nicht vernünftig erledigen. Daher versucht Perl diese Zahl so genau wie Möglich darzustellen und rundet es dann irgendwann ab einer stelle ab. So bekommen wir also durch 0.2 die Zahl "0.20000000000000001110"

Mit diesen Möglichst genauen Zahlen, aber natürlich nicht 100%ig korrekten Zahlen wird nun gerechnet. Das Ergebnis ist 11.99999999999... Und wird deswegen zu 11 gerundet.

Die Ursache ist also deswegen weil wir nur begrenzte bits haben um die Zahl zu Speichern.

Soweit korrekt?


Dann zu der anderen Frage. warum stellt er wenn ich "0.2" schreibe es intern zu "0.20000000000000001110.." dar? Also warum meint er es auf/abrunden zu müssen, obwohl ich nirgendswo hinter 0.2 noch etwas geschrieben habe? Irgendwie unlogisch. :0\n\n

<!--EDIT|sid burn|1181555900-->
Nicht mehr aktiv. Bei Kontakt: ICQ: 404181669 E-Mail: perl@david-raab.de
renee
 2007-06-11 14:02
#77435 #77435
User since
2003-08-04
14371 Artikel
ModeratorIn
[Homepage] [default_avatar]
Der Computer kann ja nicht "0.2" speichern, sondern muss das als 0en und 1en speichern und da bekommt man 0.2 nicht genau hin...

Edit: Und die Darstellung ist ja nicht unendlich lang, sondern auf eine bestimmte Länge begrenzt (je nach Genauigkeit).

Edit2: Siehe auch http://de.wikipedia.org/wiki/Gleitkommazahl\n\n

<!--EDIT|renee|1181556245-->
OTRS-Erweiterungen (http://feature-addons.de/)
Frankfurt Perlmongers (http://frankfurt.pm/)
--

Unterlagen OTRS-Workshop 2012: http://otrs.perl-services.de/workshop.html
Perl-Entwicklung: http://perl-services.de/
nepos
 2007-06-11 14:04
#77436 #77436
User since
2005-08-17
1420 Artikel
BenutzerIn
[Homepage] [default_avatar]
Weil das ganze binär gespeichert wird und dadurch nicht jede Zahl wirklich auf dem Rechner darstellbar ist?
esskar
 2007-06-11 15:03
#77437 #77437
User since
2003-08-04
7321 Artikel
ModeratorIn

user image
ich finde es nur dann ecklig, wenn man die rein-optisch gleichen zahlen miteinander vergleicht, dann aber ungleich rauskommt
sid burn
 2007-06-11 15:41
#77438 #77438
User since
2006-03-29
1520 Artikel
BenutzerIn

user image
[quote=nepos,11.June.2007, 12:04]Weil das ganze binär gespeichert wird und dadurch nicht jede Zahl wirklich auf dem Rechner darstellbar ist?[/quote]
Okay, ich glaube solangsam verstehe ich. Oder auch nicht.

Also sagen wir, wir haben eine Fließkommazahl die mit 32bit dargestellt wird. 16bits werden für die Zahl vor dem Komma 16bit für die Zahl nach dem Komma benutzt.

Und wenn ich nun "0.7" schreibe muss er das irgendwie bitweise darstellen. Wie er das genau macht weiß ich nicht. Ich würde die Zahl einfach wie mit reverse umdrehen und dann möglichst nahe veruschen heran zu kommen. Aber anscheind versucht er also die "0.7" als "70000" etc. zu speichern. Und dort versucht er es eben so nah wie Möglich an diese Zahl durch seine begrenzte Bits zu kommen.

Dass schafft er nicht, rundet also auf/ab. Er versucht also so nahe wie Möglich an diese Zahl zu kommen. Dadurch ist es also entweder mehr/weniger als gewollt.

Hmm, ich glaube ich muss mir mal anschauen wie Zahlen genau gespeichert werden... Ich finde es immer noch unlogisch...
Nicht mehr aktiv. Bei Kontakt: ICQ: 404181669 E-Mail: perl@david-raab.de
moritz
 2007-06-11 16:16
#77439 #77439
User since
2007-05-11
923 Artikel
HausmeisterIn
[Homepage]
user image
Wenn ich mich richtig erinnere, wird die 0.7 folgendermaßen in Binärdarstellung umgewandelt (bitte verbessert mich, falls es falsch ist):

0.7 > 0.5 => erste Ziffer 1
0.5 abziehen:
0.2
mit 2 multiplizieren:
0.4

0.4 < 0.5 => zweite Ziffer 0
mit 2 multiplizieren:
0.8

0.8 > 0.5 => dritte Ziffer 1
0.5 abziehen: 0.3
mit 2 multiplizieren:
0.6

0.6 > 0.5 => vierte Ziffer: 1
0.5 abziehen: 0.1
mit 2 multipzilizeren:
0.2

0.2 < 0.5 => 0
mit 2 multiplizieren: 0.4

Bei 0.4 waren wir schon mal, d.h. ab hier ist die Binärdarstellung periodisch, also

0.7 == 1(0110)*
wobei (0110)* die Periode angibt, also
10110011001100110...

Also kann man 0.7 nie genau als Binärzahl speichern.
nepos
 2007-06-11 20:11
#77440 #77440
User since
2005-08-17
1420 Artikel
BenutzerIn
[Homepage] [default_avatar]
Eventuell bringt dieser Wiki-Artikel etwas Klarheit:
http://de.wikipedia.org/wiki/IEEE_754
<< |< 1 2 >| >> 15 Einträge, 2 Seiten



View all threads created 2007-06-11 12:38.