perlunity.de - PERL | JAVASCRIPT | PHP | MySQL | APACHE



#!/COMMUNITY

Members: 5374
davon online: 1
weitere User: 21
Click for quality!




11.02.2012 / 23:31

Community-Member werden   |   Paßwort vergessen   |   OnlineMonitor (1) Wer ist online ... OnlineMonitor starten !
     

 

Home


PERLscripts


PHPscripts


JAVAscripts


Hilfreiches


Links2www


Newscenter


Community


Interna




Community  »  Perl: Allgemeines Forum zur Themenübersicht Themensuche Themenansicht in Thread-Modus


BeitragRechenfehler oder Bug ??
Seitenanfang
Hallo Zusammen,

mir ist etwas seltsames aufgefallen.

	my $wert1=47;
my $wert2=47;

for(1..50) {
$wert1-=0.1;
$wert2-=0.1;
print p("Wert1: $wert1");
print p('Wert2: ' . substr($wert2,0,4));
}

Nun die Ausgabe ab dem 34. Wert:

...
Wert1: 43.6
Wert2: 43.6

Wert1: 43.5
Wert2: 43.5

Wert1: 43.3999999999999
Wert2: 43.3

Wert1: 43.2999999999999
Wert2: 43.2

Wert1: 43.1999999999999
Wert2: 43.1

Wert1: 43.0999999999999
Wert2: 43.0

Wert1: 42.9999999999999
Wert2: 42.9

Wert1: 42.8999999999999
Wert2: 42.8

Wert1: 42.7999999999999
Wert2: 42.7
[...]

Wert1: Es sieht so aus, dass sich Perl verrechnet.

Wert2: Wenn man mit substr arbeitet ist die Ausgabe korrekt.

Kennt von euch jemand dieses Problem?

Benutze Active State Perl 6.8.x

Gruß
mat
Wenn man a

Datum: 07.09.2005-08:08

Beitragre: Rechenfehler oder Bug ??
Seitenanfang
Die Ausgabe von Wert2 ist auch nicht korrekt!!!
43.4 fehlt, statt dessen gehts da mit 43.3 weiter!!!
frag mich aber nicht woran das liegt

Datum: 07.09.2005-08:26

Beitragre: Rechenfehler oder Bug ??
Seitenanfang
Danke TommyB,

das habe ich wohl übersehen.

Jetzt stimmt wenigstens der "falsche" Wert2...

Datum: 07.09.2005-09:05

Beitragre: Rechenfehler oder Bug ??
Seitenanfang
Rechenungenauigkeit wuerd ich mal schaetzen..

Der "Huepfer" tritt immer nach dem 36mal auf. Und nach dem 53ten Abzug "korrigiert er sich wieder.

Bsp:


$x = 20;
for (1..80) { $x-=0.1; print "$_ $x\n"; }
Ergibt dann:

..
35 16.5
36 16.3999999999999
37 16.2999999999999
38 16.1999999999999
39 16.0999999999999
40 15.9999999999999
41 15.8999999999999
42 15.7999999999999
43 15.6999999999999
44 15.5999999999999
45 15.4999999999999
46 15.3999999999999
47 15.2999999999999
48 15.1999999999999
49 15.0999999999999
50 14.9999999999999
51 14.8999999999999
52 14.7999999999999
53 14.7
..

Schreibt man $x = $x - 0.1; statt $x-=0.1; tritt der Fehler auch auf. Mit sprintf dagegen nicht mehr:

$x = 20;
for (1..80) { $x = sprintf '%6.3f', $x - 0.1; print "$_ $x\n"; }

Also wirklich nur beim dekrementieren, denn das hier funktioniert auch korrekt:

my $x=20;
for (1..80) { printf \"%d %6.3f\n\", $_, $x-($_*0.1); }

Datum: 07.09.2005-14:00

Beitragre: Rechenfehler oder Bug ??
Seitenanfang
Das Fehlverhalten ist auch vom Ausgangswert abhängig. Setz mal x=30;

PS: Auf Linux und UNIX habe ich gleiche Ergebnisse bekommen, ist also ein globales Problem.

Datum: 07.09.2005-15:08

Beitragre: Rechenfehler oder Bug ?? - Nachtrag
Seitenanfang
Definitiv Rechenungenauigkeit, bzw. Rundungsfehler.
use Math::BigFloat;
my $x=Math::BigFloat->new('20');
for(1..80){
$x-=0.1;
print "$_ $x\n";
}
funktioniert wie erwartet.

Datum: 07.09.2005-14:08

Beitragre: Rechenfehler oder Bug ?? - Nachtrag
Seitenanfang
Bin auf das Ergebnis von Math::BigFloat gespannt.

Datum: 07.09.2005-21:29

Beitragre: Rechenfehler oder Bug ??
Seitenanfang
Quelle: http://perldoc.perl.org/perlfaq4.html

Data: Numbers
Why am I getting long decimals (eg, 19.9499999999999) instead of the numbers I should be getting (eg, 19.95)?

Internally, your computer represents floating-point numbers in binary. Digital (as in powers of two) computers cannot store all numbers exactly. Some real numbers lose precision in the process. This is a problem with how computers store numbers and affects all computer languages, not just Perl.

perlnumber show the gory details of number representations and conversions.

To limit the number of decimal places in your numbers, you can use the printf or sprintf function. See the "Floating Point Arithmetic" for more details.

printf "%.2f", 10/3;

my $number = sprintf "%.2f", 10/3;

Aha

Datum: 07.09.2005-22:08

-






-
-