Jemand zu Hause?Leser: 20
Math::Round
Math::Round hat zwei einfache Testfälle komplett falsch gemacht!1 2 3 4 5 6 7 8
#!/usr/bin/perl use strict; use warnings; use diagnostics; use Math::Round; my $var = '0.05499999999999999334'; print nearest(.01, $var); print round($var);
Quote0.060
say nearest(0.01, 0.005); # 0.005 auf 2 Nachkommastellen runden
say nearest(0.01, 2.024-2.019); # 2.024-2.019 = 0.005
say 2.024-2.019;
2013-09-25T06:56:28 MuffiKAUFMÄNNISCHE RUNDUNG IST MIT FLIESSKOMMAZAHLEN NICHT ZU MACHEN!
Es geht nicht! Glaubs halt endlich.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
sub runden { my $zahl=shift; return undef unless(defined($zahl)); my $stelle=shift || 0; # prepare for Xe[+-]Y Notation # handle big float my ($pre,$number,$exponent)=$zahl=~/^([-+]?)([\d.]+)(?:e([+-]?\d+))?$/; $exponent=0 unless defined($exponent); $pre='' if(!$pre || $pre ne '-'); # full integer number with exponent my ($l)=$number=~/\.(.+)$/; $exponent-=$l?length($l):0; $number=~y/.//d; # correct position for round my $stellen=$stelle+$exponent; if($stellen<0) { $exponent=-$stelle; my $add=substr(('0'x abs($stellen)).$number,$stellen,-$stellen); # round... $number+=$add; $number=('0'x abs($stellen)).sprintf("%.0f",$number); substr($number,$stellen,-$stellen,''); } # reconstruct number $zahl="$pre${number}e$exponent"; # format number if($zahl==0) { $zahl='0'; } else { $zahl=sprintf("%.${stelle}f",$zahl); $zahl=~s/\.?0+$// if(index($zahl,'.')>0) } return $zahl; }
2013-09-25T07:07:10 bianca2013-09-25T06:56:28 MuffiKAUFMÄNNISCHE RUNDUNG IST MIT FLIESSKOMMAZAHLEN NICHT ZU MACHEN!
Es geht nicht! Glaubs halt endlich.
Und wieso kann man mit Computern trotzdem kaufmännische Anwendungen benutzen?
Math::Round (oder ähnliche Module, bei denen sich Leute viel Gedanken drüber gemacht haben, wie man beim Runden standardmässig schon am öftesten richtig liegt). Und wenn man verstanden hat wie Fließkommazahlen funktionieren kann man damit gut arbeiten und es kommen auch die erwarteten Ergebnisse raus.
1 2 3
use Math::Round; $Math::Round::half = 0.5; say nearest(0.01, '0.05499999999999999334');
2013-09-25T07:32:47 MuffiNein, der Testcode war nicht falsch.
Wenn du $Math::Round::half auf 0.5 setzt gehen andere Testfälle kaputt. Drum stehts ja standardmässig nicht auf 0.5.
2013-09-24T09:10:22 Muffi
2013-09-25T09:43:42 MuffiDeine Testfälle sind halt nicht wirklich realistisch.
2013-09-25T09:43:42 MuffiViel wahrscheinlicher ist doch wohl, dass die Zahl durch eine Berechnung entstand und eigentlich 2.5 heißt.
2013-09-25T09:43:42 MuffiUnd falls dem wirklich nicht so ist kannst du mit dem Parameter, den ich dir gezeigt hab das Verhalten umstellen.
Math::Round :)2013-09-25T09:43:42 MuffiOch, wenn sie Tests schreibt, um zu vermeiden, dass ein Programm/Modul falsch rechnet, sind solche Testfälle sehr wohl realistisch.Deine Testfälle sind halt nicht wirklich realistisch.
2013-09-25T10:55:17 MuffiDeine Lösung rundet die Benutzereingaben richtig, die Berechnungen falsch.
2013-09-25T10:55:17 MuffiMeine letzte Antwort dazu, ich bin mittlerweile fest davon überzeugt du wirsts nie kapieren.
2013-09-25T10:50:25 Muffirecht praktisch vorkommende rechnet sie dafür falsch.
say neueloesung(2.024-2.019, 2);
2013-09-25T10:02:42 Muffi
2013-09-25T17:04:02 hlubenow
Wie frage ich & perlintro
brian's Leitfaden für jedes Perl-Problem2013-09-25T10:55:17 MuffiDeine Lösung rundet die Benutzereingaben richtig, die Berechnungen falsch.
2013-09-26T04:57:08 biancaAber ist das die Erklärung zu dieser für mich neuen Aussage?
Wie frage ich & perlintro
brian's Leitfaden für jedes Perl-Problemsay nearest(0.01, 0.004999999999998+0.000000000000001);
1 2 3 4 5 6
my $a = 5; # 5 Euro auf dem Konto $a += 0.01 for (1..50); # Gutschrift von 50 mal 1 Cent # hier den Kontostand kaufmännisch gerundet auf ganze Euro # Erwartet: 5 Euro + 50 * 1 Cent = 5,50 Euro; Kaufm. Ger. = 6 Euro ...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
5.01 => 5
5.02 => 5
5.03 => 5
5.04 => 5
5.05 => 5
5.06 => 5
5.07 => 5
5.08 => 5
5.09 => 5
5.1 => 5
5.11 => 5
5.12 => 5
5.13 => 5
5.14 => 5
5.15 => 5
5.16 => 5
5.17 => 5
5.18 => 5
5.19 => 5
5.2 => 5
5.21 => 5
5.22 => 5
5.23 => 5
5.23999999999999 => 5
5.24999999999999 => 5
5.25999999999999 => 5
5.26999999999999 => 5
5.27999999999999 => 5
5.28999999999999 => 5
5.29999999999999 => 5
5.30999999999999 => 5
5.31999999999999 => 5
5.32999999999999 => 5
5.33999999999999 => 5
5.34999999999999 => 5
5.35999999999999 => 5
5.36999999999999 => 5
5.37999999999999 => 5
5.38999999999999 => 5
5.39999999999999 => 5
5.40999999999999 => 5
5.41999999999999 => 5
5.42999999999999 => 5
5.43999999999999 => 5
5.44999999999999 => 5
5.45999999999999 => 5
5.46999999999999 => 5
5.47999999999999 => 5
5.48999999999999 => 5
5.49999999999999 => 5
hingegen 5.5 auf 0: 6
2013-09-26T08:52:34 MuffiWodurch dann dein Vorwurf an mich, ich solle hier nicht Module empfehlen, wenn ich keine Ahnung von den Anforderungen habe wohl dann auch für die Tonne ist.