1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
#!/usr/bin/perl -w use strict; use warnings; my $a = integer(100000 + -1.45519152283669e-011 ); my $b = 100000; my $test = $a - $b; print "$a minus $b = $test\n"; sub integer { my $wert = shift (@_) || 0; return 'FEHLER' if $wert =~ /e\+?\d+$/; return 0 if $wert =~ /e-\d+$/; $wert = $1 if $wert =~ /^(.*?)\./; $wert = 0 if !$wert or $wert == -0; return $wert; }
Quote100000 minus 100000 = -1.45519152283669e-011
1
2
3
4
$ perl -wE'say 100000 + -1.45519152283669e-011'
100000
$ perl -wE'say sprintf("%.12f",100000 + -1.45519152283669e-011)'
99999.999999999985
2013-04-27T11:55:08 RaubtierWas spricht gegen die Perl-eigenen Funktionen zum (Ab-, Auf-)Runden?
2013-04-27T11:55:08 RaubtierAbgesehen davon, dass dein Code falsch ist, ist er auch noch ineffizient. Warum eine Zahl in einen String wandeln und dann ggf. wieder zurück, wenn man auch direkt mit der Zahl rechnen kann.
2013-04-27T12:24:54 bianca2013-04-27T11:55:08 RaubtierWas spricht gegen die Perl-eigenen Funktionen zum (Ab-, Auf-)Runden?
Es spricht dagegen, dass sie noch schlechter funktionieren, das hatten wir hier diskutiert: Richtig INTen und hier Perl Bug bei int?
2013-04-27T15:33:15 tonewheelOhnehin kennt Perl intern kein Integer. Es liegt alles im float Format vor. Ausserdem wird bei Bedarf gecastet. Addiert man also 1000 + 1000.0001, so wird daraus 1000.0 + 1000.0001
2013-04-27T15:33:15 tonewheelTipp: 'Learning Perl' gut durchlesen. Das ist durchaus mehr als nur ein Anfängerbuch, denn gerade diese Sachverhalte sind da wunderbar erklärt.
2013-04-27T16:50:49 biancaUnd wie wir man dem Herr?
2013-04-27T16:50:49 biancaSteht da auch drin, wie man dem Computer das Rechnen beibringt? :)
2013-04-27T16:50:49 biancaAlso findet man darin eine Lösung, wie man beliebige ganzzahlige Werte in beliebiger Menge addiert und am Ende noch 100000 == 100000 ist?
my $test = sprintf("%d", $a - $b);
my $money = sprintf("%.2f", 2.49997);
QuoteDaher nochmal die Frage: Was muss ich denn tun, damit meine Anwendung auch intern mit den Ganzzahlen mathematisch korrekt addiert?
2013-04-27T18:09:07 MuffiDie integerfunktion weglassen
1 2 3 4 5 6 7 8 9 10
#!/usr/bin/perl -w use strict; use warnings; my $a = 0.57; my $b = 100; my $c = sprintf("%0.0f", $a * $b); print $c . "\n";
1 2 3 4 5 6 7 8
my $epsilon = 0.00000001; my $a = ....; # irgendein errechneter float wert my $b = ....; # noch irgendein errechneter float wert if (abs($a - $b) < $epsilon) # In dem Fall 'sieht man es als 0 an' else my $differenz = $a - $b;
2013-04-27T18:21:55 tonewheelIch nehme nun an, dass diese 'Summen', die Du erwähnst, Integerzahlen sein sollen?!
2013-04-27T18:21:55 tonewheelAntwort für Integer: Hast Du mal die modifizierte Zeile 8 ausprobiert? Liefert die nicht genau das, was Du willst? Sie ist ausreichend, um den 'Rundungsfehler' von Perl zu verhindern.
2013-04-27T18:21:55 tonewheelAntwort für Float: Da Float Werte nie 'gleich' sind (das liegt nicht an Perl, oder am Computer, sondern einfach nur daran, dass man mit endlich vielen Binärstellen keine reelle Zahl darstellen kann), legt man fest, wann etwas 'als gleich gelten soll'. Dann tut man, ähnlich der Mathematik; man legt ein epsilon fest, das die Abweichung anzeigt, die noch als gleich gilt:
2013-04-27T18:33:46 biancaAus den anderen drei erwähnten Threads ist bei mir hängen geblieben, dass man beim Rechnen Abstand von sprintf nehmen sollte.
2013-04-27T18:33:46 biancaJa, kann ich nachvollziehen. Würde auch das aktuelle Problem lösen.
2013-04-27T18:33:46 biancaAber eine wichtige Frage bleibt bei mir offen: Wieso enthält eine Variable offensichtlich intern einen anderen Wert als der, den man mit print anzeigen lassen kann? Das gibt mir das Gefühl, keine Kontrolle über die
2013-04-27T18:33:46 biancaWerte zu haben und damit nie sicher zu sein, dass meine Summe am Ende stimmt.
2013-04-27T18:33:46 biancaDas birgt ja das mit der Anzahl der Einzelwerte zunehmende Risiko, dass sich hier nicht sichtbar zu machende Differenzen ergeben, die sich aufschaukeln.
2013-04-27T18:33:46 biancaGibt es denn keine Möglichkeit sicherzustellen, dass eine Variable das enthält, was man auch "sehen" kann?
2013-04-28T06:54:21 tonewheelJedoch, warum die Einzelwerte mit 100 multiplizieren?
2013-04-27T15:33:15 tonewheelOhnehin kennt Perl intern kein Integer. Es liegt alles im float Format vor.
2013-04-28T07:31:57 ?@topic: gut getrollt... dass dir nicht langweilig wird
2013-04-28T09:29:09 MuffiWahrscheinlich soll einem das sagen, dass man mit Perl besser nix mathematisches macht.
2013-04-28T08:04:17 tonewheel'Learning Perl', 5th Edition (neben einigen anderen)
'....... But internally, Perl computes with double-precision floating-point values. This means, there are no integer values internal to Perl
QuoteInternally, native integer arithmetic (as provided by your C compiler) is used. This means that Perl's own semantics for arithmetic operations may not be preserved. One common source of trouble is the modulus of negative numbers, which Perl does one way, but your hardware may do another.
2013-04-28T07:31:57 betterworld@topic: gut getrollt... dass dir nicht langweilig wird
2013-04-27T12:53:56 RaubtierIch glaube, es ist viel wichtiger, dass du genau beschreibst, wie eigentlich gerundet werden soll, wenn du Fließkommazahlen verwendest.
2013-04-27T18:02:34 MuffiDann musst du wohl genauer beschreiben, wer das wir beim erarbeiten war.
2013-04-27T18:02:34 MuffiIch halt die Funktion nach wie vor für quatsch. Ich hab damals auch einen Vorschlag für Auf- und Abrunden gepostet.
2013-04-27T18:02:34 MuffiAnsonsten les ich öfter bei dir was von falsch. Das ist ungefähr so, wie wenn du dich in ein Auto setzt, keine Ahnung hast was das Runde vor dir und die Pedale unter dir sind und sagst es fährt falsch. Deshalb baust du dir jetzt ne wilde Apparatur, die alles bedient und automatisch dahin fährt wo du grad drandenkst. Da sie aber dann doch keine Gedanken lesen kann fährt sie meist in den Graben.