cgi kann nicht rechnen
Jörg Wittemeier
Hallo !!
Habe ein kleines, aber nicht unwichtiges cgi-Problem (Perl):
$test=3*529.95;
print "$test";
Die Ausgabe sieht dann so aus:
1589.8500000000001364
Sobald keine ganzen Zahlen im Spiel sind kommt es
zu diesen Merkwürdigkeiten. Auch bei einer Division !
Nun habe ich vor einigen Tagen diese Frage hier im Forum
schon einmal gestellt und als Antwort "falsche Serverkonfiguration"
erhalten. Habe den Server gewechselt und: gleicher Fehler !
Kann doch kein Zufall sein. Oder doch?
Gruß
Jörg
Hallo Jörg !!
$test=3*529.95;
print "$test";Die Ausgabe sieht dann so aus:
1589.8500000000001364
Ich muß vorausschicken, ich bin eine Patchworktante, die das Programmieren nicht gelernt hat.
Deshalb ist ein Tip von mir nicht der Weisheit letzter Schluß.
Aber ich lasse mich von solchen Sachen nicht ärgern, sondern arbeite nur mit ganzen Zahlen und dividiere erst zum Schluß.
Will sagen, z.B. in meinem JavaScript-Warenkorb wird mit Pfennigen gerechnet, und das Ergebnis zum Schluß erst in DM ausgegeben
Das würde dann wohl so aussehen:
3*52995/100
Gruß Jutta
Hallo Jörg !!
$test=3*529.95;
print "$test";Die Ausgabe sieht dann so aus:
1589.8500000000001364
Ich muß vorausschicken, ich bin eine Patchworktante, die das Programmieren nicht gelernt hat.
Deshalb ist ein Tip von mir nicht der Weisheit letzter Schluß.Aber ich lasse mich von solchen Sachen nicht ärgern, sondern arbeite nur mit ganzen Zahlen und dividiere erst zum Schluß.
Will sagen, z.B. in meinem JavaScript-Warenkorb wird mit Pfennigen gerechnet, und das Ergebnis zum Schluß erst in DM ausgegeben
Das würde dann wohl so aussehen:
3*52995/100Gruß Jutta
Hallo Jutta !
Leider hilft mir das auch nicht weiter.
Unter Perl ergibt 3*52995/100
genau 1589,8499999999999091 :-((
Es handelt sich übrigens auch um ein Shopping-Sytem.
Unter UNIX läuft es, aber unter einem anderem
Betriebssystem nicht:
Gruß
Jörg
Hallo Joerg,
$test=3*529.95;
print "$test";
Die Ausgabe sieht dann so aus:
1589.8500000000001364
Scheint tatsaechlich eher was mit dem Server-Rechner zu tun zu haben. Hab's gerade mal bei mir lokal als kleines CGI-Script getestet und heraus kam 1589.85.
Viele Gruesse
Stefan Muenz
Hallo Joerg,
$test=3*529.95;
print "$test";
Die Ausgabe sieht dann so aus:
1589.8500000000001364Scheint tatsaechlich eher was mit dem Server-Rechner zu tun zu haben. Hab's gerade mal bei mir lokal als kleines CGI-Script getestet und heraus kam 1589.85.
Viele Gruesse
Stefan Muenz
Hallo Stefan !
Habe mein Shopping-System nun auf 3 ! Servern getestet.
Der dritte war ein UNIX - Server und dort lief die Multiplikation
perfekt und ohne Rechenfehler.
Weiß leider noch nicht, mit welchem Betriebssystem die zwei anderen
laufen. War jedenfalls nicht UNIX. Muß mich noch kundig machen.
Kann doch aber nicht die Lösung sein, daß Berechnungen mit
Perl nur unter bestimmten Betriebstsystemen laufen.
Gruß
Jörg
Hallo !!
Habe ein kleines, aber nicht unwichtiges cgi-Problem (Perl):
$test=3*529.95;
print "$test";Die Ausgabe sieht dann so aus:
1589.8500000000001364
Hallo Jörg!
Dein Problem ist prinzipieller Natur: Die Zahl
529.95, welche zunächst recht harmlos wirkt,
wird in der Binärdarstellung des Computers zu einem
periodischen, nicht-abbrechenden Dezimalbruch.
(Beispiel:
0.95 = 1-1/20,
1/20 (dezimal) = 1/10100 (binär)
= 0.0000110011001100....(binär)
)
Jetzt kommt es eben darauf an, wieviele Binärstellen der Perl-Interpreter
für eine Real-Zahl verwendet. In den letzten Stellen ist ein Rundungsfehler
immer vorprogrammiert.
Bei Zahlen, die sich glatt darstellen lassen, z.B. 0.25 = 0.01(binär),
sollten derartige Probleme dagegen nicht auftreten (ausprobieren!).
Ich habe mit Perl noch nicht viel gemacht, denke aber, daß es
irgendwelche Operatoren geben müßte, um Zahlen formatiert
Viele Grüße,
Andreas
Nachtrag:
probier mal:
$x=595.95*3;
$y=int(x*100+0.5)/100;
print $y/100;
Damit wird die Rundung auf 2 Nachkommastellen erzwungen.
Die Rundung sollte jedoch immer erst unmittelbar vor der Ausgabe
(oder in der Ausgabe) geschehen.
Viele Grüße
Andreas
P.S.: 0.95 (dezimal) wird im Binärsystem zu einem nicht-abbrechenden BINÄR-Bruch
(Asche über mein Haupt...).
Nachtrag:
probier mal:
$x=595.95*3;
$y=int(x*100+0.5)/100;print $y/100;
Damit wird die Rundung auf 2 Nachkommastellen erzwungen.
Die Rundung sollte jedoch immer erst unmittelbar vor der Ausgabe
(oder in der Ausgabe) geschehen.Viele Grüße
Andreas
P.S.: 0.95 (dezimal) wird im Binärsystem zu einem nicht-abbrechenden BINÄR-Bruch
(Asche über mein Haupt...).
Hallo Andreas !
Danke für die kompetente Antwort. Hat mir insofern weitergeholfen,
daß ich den Fehler nicht mehr in der Server-Konfiguration gesucht habe.
Das mit der Rundung funktionierte auch nicht.
Kam irgenetwas .99999999990123 herraus.
Hier meine Lösung:
$ALL=529.95*3;
$ALL=$ALL+0.001;
$ALL=substr($ALL,0,index("$ALL",".")+3);
print "$ALL";
Die 0.001 addiere ich für die xxx.999999999990123 Ergebnisse.
Das Ganze hat den netten Nebeneffekt, daß die Ausgabe immer
mit 2 Stellen hinter dem Komma erfolgt.
Gruß
Jörg
Hier meine Lösung:
$ALL=529.95*3;
$ALL=$ALL+0.001;
$ALL=substr($ALL,0,index("$ALL",".")+3);
print "$ALL";Die 0.001 addiere ich für die xxx.999999999990123 Ergebnisse.
Das Ganze hat den netten Nebeneffekt, daß die Ausgabe immer
mit 2 Stellen hinter dem Komma erfolgt.
»» Gruß
Jörg
Hallo Jörg!
Was machst Du mit Zahlen wie z.B. 14.976?
Nach Deiner Rundung müßte 14.97 herauskommen, richtig wäre aber 14.98
Mein Vorschlag ist daher
$ALL=$ALL+0.005
in Deinen obigen Zeilen einzusetzen, ferner noch eine
Fallunterscheidung für negative Zahlen...
So, jetzt hab' ich mich als Haarespalter geoutet ;-)
Frage ans Forum: Gibt es wirklich keinen formatierten Print-Befehl unter PERL??
Viele Grüße
Andreas
Hallo Andreas !
Was machst Du mit Zahlen wie z.B. 14.976?
Kommt bei mir nicht vor. Ist ein Online-Shopping-System
mit einfacher Multiplikation.
Werde mir dennoch Gedanken machen (spätestens bei Berechnung der MWST) :-))
Mein Vorschlag ist daher
$ALL=$ALL+0.005
Funzt nicht, da 0.001 ja die .9999999 beseitigen soll.
Formatieren wäre sicherlich die beste Lösung, aber wie??
Gruß
Jörg