2013-04-27T18:18:05 MuffiRunden deswegen, weil du eine Fliesskommazahl zum nächsten int hinrunden wolltest.
if abs($rechnung - 57) < $epsilon
2013-04-27T18:21:05 biancaFängt ja schon hier an das Problem:
print "\n".(.57 * 100 == 57 ? 'ja' : 'nein')."\n";
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
#include <stdio.h> int main() { printf("%f\n", .57 * 100); if (.57 * 100 == 57) { puts("ja"); } else { puts("nein"); } if (.57 * 100.0 == 57.000000) { puts("ja"); } else { puts("nein"); } }
2013-04-28T19:14:30 hlubenow(was man vom Computer auch zu Recht erwartet).
2013-04-28T21:08:31 RaubtierWurde aber beides schon vorgeschlagen. Daher bin ich auch ratlos, wie man weiter helfen könnte.
2013-04-29T06:32:30 MuffiAlso lass deine Fliesskommazahlen einfach Flieskommazahlen sein, das tut ja nicht weh. Durch irgendwelches rumgeschneide und gecaste nach integer/string oder sonstwas wirds nur ungenauer.
Wenn du im Hinterkopf hast, dass Fliesskommazahlen einfach immer und in JEDER Programmiersprache ein klein wenig neben dem liegen können was du erwartest und das z.B. bei Vergleichen berücksichtigst ist das auch nicht mehr so schlimm.
Und bei der Ausgabe! (und nur da) kannst du z.B. mit printf angeben wie und mit wie vielen Stellen dus denn gern angezeigt haben willst.
Aber das schon bei Berechnungen zu tun bringt ind er Regel keinen Vorteil.
2013-04-29T06:32:30 Muffi[...]
Wenn du im Hinterkopf hast, dass Fliesskommazahlen einfach immer und in JEDER Programmiersprache ein klein wenig neben dem liegen können was du erwartest und das z.B. bei Vergleichen berücksichtigst ist das auch nicht mehr so schlimm.
[...]
2013-04-27T18:21:05 biancaAber funktioniert ja alles nicht, egal was ich versuche.
Fängt ja schon hier an das Problem:
print "\n".(.57 * 100 == 57 ? 'ja' : 'nein')."\n";
1 2 3 4 5 6 7 8
use strict; use warnings; my $f = 0.57; my $f100 = $f * 100; print ($f100 == 57 ? 'ja' : 'nein', "\n"); my $i100 = sprintf('%.0f', $f * 100); print ($i100 == 57 ? 'ja' : 'nein', "\n");
Quotenein
ja
Quote((1 - 0.9999) * 10000)
Das sollte 1 ergeben.
1 2 3 4 5 6
use strict; use warnings; my $f = 0.9999; my $f_faktor = 10000; my $f_int = sprintf('%.0f', $f * $f_faktor); print ((1*$f_faktor - $f_int) * 10000 == 1*$f_faktor ? 'ja' : 'nein', "\n");
2013-04-29T14:32:35 GUIfreundMein Fazit: Nach dem Multiplizieren zu Integer sofort runden.
2013-04-29T17:43:01 biancaMein Fazit ist ganz klar: Ohne bestimmte Rechen-Zusatzmodule gehe ich davon aus, dass eine Variable grundsätzlich niemals den Wert enthält, der einem mit print angezeigt wird.
2013-04-29T17:43:01 biancaWeiterhin gehe ich aber davon aus, dass die Abweichung zwischen der Anzeige und dem tatsächlichen Wert so klein ist, dass sie meine Berechnungen nicht beeinflusst. Solange ich keine Raketenumlaufbahn damit berechne, sollte das klar gehen.
2013-04-29T19:33:27 hlubenowaber trotzdem zeigt die Erfahrung, daß es sich wegen des Problems in seltenen, schwer vorherzusagenden Fällen doch mal um einen Cent verschieben kann.
2013-04-29T19:33:27 hlubenowBin nicht sicher, ob man den Modulen da immer vertrauen kann. Wenn man's schon der Standardsprache in dieser Hinsicht nicht kann, in der die Module ja geschrieben sind. Ich persönlich würde mir im Zweifel lieber nicht sagen, "ach, das Modul wird das schon machen".
Mehrwertsteueranteil jetzt 100/119 sein oder 119/100 oder wie nun?
2013-04-30T07:15:08 tonewheel2013-04-29T19:33:27 hlubenowBin nicht sicher, ob man den Modulen da immer vertrauen kann. Wenn man's schon der Standardsprache in dieser Hinsicht nicht kann, in der die Module ja geschrieben sind. Ich persönlich würde mir im Zweifel lieber nicht sagen, "ach, das Modul wird das schon machen".
Mehrwertsteueranteil jetzt 100/119 sein oder 119/100 oder wie nun?
Wenn Du an solch grundlegenden Dingen schon Gedanken verschwenden musst, bezweifle ich, dass Du die (Un)Genauigkeit eines Moduls beurteilen kannst. Diese unterliegt klaren Kriterien.
2013-04-30T07:15:08 tonewheelDa Du, wie Du schreibst, schon einige Zeilen in Python und Perl/TK geschrieben hast, solltest Du Dich nun mit C, oder besser Assembler beschäftigen, um zu lernen, wie ein Computer funktioniert.
2013-04-30T20:02:59 hlubenow...Ich will, daß mir solche Fragen von der Sprache, bzw. vom Interpreter abgenommen werden. Ich will schnell vorankommen! Und deshalb will ich natürlich auch, daß eine Prüfung von "0.57 * 100" ein reines "57" ergibt. Sonst gehe ich erstmal davon aus, daß der Interpreter kaputt ist. Es wäre seine Aufgabe, mich von solchen Low-Level-Fragen fernzuhalten. Wahrscheinlich sollte die Regelung des Problems tatsächlich in den Interpreter eingearbeitet werden.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
#!/usr/bin/perl use warnings; use strict; my $b = 0.57; my $BITS = -24; my $BASE = 2; for(my $c = -1; $c >= $BITS; $c--) { if (($BASE ** $c) < $b) { printf("Bit %2d: %0.15f - %0.15f = %0.15f\n", -$c, $b, $BASE ** $c, $b - $BASE ** $c); $b -= $BASE ** $c; } }
2013-05-01T14:01:03 tonewheelIm gegebenen Fall - d.h. wenn es um Währungen geht, wenn ich das richtig interpretiert habe - sollte man völlig auf Dezimalbrüche verzichten und die Beträge einfach in der Einheit Cent einfordern.
tonewheelDas ist aber alles Sache des Rechners selbst, weder die Hostsprache C, noch Perl selbst kann das irgendwie kompensieren. Man kann auch nichts in den Interpreter einbauen, denn wie sollte das aussehen?
QuoteWarning: Bits cutoff in decimal operation, at line ...
tonewheelIm gegebenen Fall - d.h. wenn es um Währungen geht, wenn ich das richtig interpretiert habe - sollte man völlig auf Dezimalbrüche verzichten und die Beträge einfach in der Einheit Cent einfordern. D.h statt 1000,00 Euro wird 100000 Cent eingeben.
2013-05-01T16:34:13 hlubenowAua.Die Wandlung von "1000,00" zu "10000" ...
2013-05-01T16:34:13 hlubenowP.S.: Ich konnte innerhalb der Thread-Struktur nicht direkt auf den Beitrag antworten, vielleicht, weil das Maximum der Unterpunkte erreicht wurde?
2013-05-01T16:52:24 GUIfreund2013-05-01T16:34:13 hlubenowP.S.: Ich konnte innerhalb der Thread-Struktur nicht direkt auf den Beitrag antworten, vielleicht, weil das Maximum der Unterpunkte erreicht wurde?
Vielleicht, weil ich gerade beim Antworten war?
perl -e 'print 3537 * 19 / 119 . "\n"'
2013-05-01T16:56:30 hlubenowDas wären also 3537 Cents * 19 / 119.
2013-05-01T16:56:30 hlubenowÖhm, wenn ich bei meinem Mehrwertsteuerprogramm versuche, alles in Cents zu rechnen, bekomme ich aber auch ein Problem (beim Teilen):
Angenommen, ich will von 35,37 EUR brutto die darin enthaltene Mehrwertsteuer berechnen. Das wären also 3537 Cents * 19 / 119.
Code: (dl )perl -e 'print 3537 * 19 / 119 . "\n"'
Ergebnis: 564,73.... Cents. Dann müßte ich das Ergebnis dann ja doch noch wieder runden, hier auf 565 Cents.
Man kann also auch beim Rechnen in Cents nicht einfach alles mit Integern machen. Schade.
perl -e 'printf("%0.0f\n", 3537 * 19 / 119)'
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# perl -wle 'for ($i = 0; $i < 1.01; $i += 0.05) { printf "%.2f %.1f \n",$i,$i}'
0.00 0.0
0.05 0.1
0.10 0.1
0.15 0.2
0.20 0.2
0.25 0.2 <<<<
0.30 0.3
0.35 0.3 <<<<
0.40 0.4
0.45 0.4 <<<<
0.50 0.5
0.55 0.5 <<<<
0.60 0.6
0.65 0.7
0.70 0.7
0.75 0.8
0.80 0.8
0.85 0.9
0.90 0.9
0.95 1.0
1.00 1.0
QuoteDon't blame Perl. It's the same as in C. IEEE says we have to do this. Perl numbers whose absolute values are integers under 2**31 (on 32-bit machines) will work pretty much like mathematical integers. Other numbers are not guaranteed.
1
2
3
4
var i;
for(i = 0; i < 1.01; i += 0.05) {
document.writeln(i.toPrecision(2) + " " + i.toPrecision(1) + " " + i.toPrecision(20));
}
Quote0.0 0 0.0000000000000000000
0.050 0.05 0.050000000000000002776
0.10 0.1 0.10000000000000000555
0.15 0.2 0.15000000000000002220
0.20 0.2 0.20000000000000001110
0.25 0.3 0.25000000000000000000
0.30 0.3 0.29999999999999998890
0.35 0.3 0.34999999999999997780
0.40 0.4 0.39999999999999996669
0.45 0.4 0.44999999999999995559
0.50 0.5 0.49999999999999994449
0.55 0.5 0.54999999999999993339
0.60 0.6 0.59999999999999997780
0.65 0.7 0.65000000000000002220
0.70 0.7 0.70000000000000006661
0.75 0.8 0.75000000000000011102
0.80 0.8 0.80000000000000015543
0.85 0.9 0.85000000000000019984
0.90 0.9 0.90000000000000024425
0.95 1 0.95000000000000028866
1.0 1 1.0000000000000002220
2013-05-01T21:47:17 tonewheelHier ein Beispiel in JavaScript
2013-05-02T04:35:48 bianca2013-05-01T21:47:17 tonewheelHier ein Beispiel in JavaScript
Da hatte ich mit toFixed() einige gute Ergebnisse erhalten aber nicht in die Tiefe getestet. Wieso hast du toPrecision() verwendet? Wo ist der Unterschied?
perl -e 'print int(3537 * 19 / 119 + 0.5) . "\n"'
$rounded_int = int($float + 0.50000000000008);
Guest werÜbers korrekte Runden wurde schon in zwei anderen Threads ausführlich geschrieben. Ein Ergebnis war das sprintf sich nicht zum runden eignet da es Fehler macht.
2013-05-01T16:34:13 hlubenowP.S.: Ich konnte innerhalb der Thread-Struktur nicht direkt auf den Beitrag antworten, vielleicht, weil das Maximum der Unterpunkte erreicht wurde?
2013-04-29T17:43:01 bianca2013-04-29T14:32:35 GUIfreundMein Fazit: Nach dem Multiplizieren zu Integer sofort runden.
Jetzt wird es aber ganz haarsträubend :)
Das integer'n sollte ja Rechenfehler verhindern. Und rein gedanklich sollte doch ein ganzzahliger Wert nicht mehr gerundet werden müssen, oder?
2013-04-30T07:40:50 MuffiIch hab jetzt länger überlegt was man da schreiben soll.
Da geht 2 Threads lang um das Thema mit dem Ergebnis, dass zum Schluss wieder einer mit sprintf-hokuspokus anfängt.
2013-04-30T07:40:50 MuffiWenn du bei ((1 - 0.9999) * 10000) die Genauigkeit erhöhen willst musst du versuchen keine ähnlich grossen Zahlen voneinander zu subtrahieren. Z.b. mit dem 10000 nach innen.
(1*10000 - 0.9999*10000) sollt genauer sein.
Aber das wars dann auch schon.