|
1 |
use strict;
|
|
2 |
use Test::More;
|
|
3 |
|
|
4 |
use lib 't';
|
|
5 |
use Support::TestSetup;
|
|
6 |
|
|
7 |
Support::TestSetup::login();
|
|
8 |
|
|
9 |
my $config = {};
|
|
10 |
|
|
11 |
$config->{numberformat} = '1.000,00';
|
|
12 |
|
|
13 |
# Positive values
|
|
14 |
is($::form->round_amount(1.05, 2), '1.05', '1.05 @ 2');
|
|
15 |
is($::form->round_amount(1.05, 1), '1.1', '1.05 @ 1');
|
|
16 |
is($::form->round_amount(1.05, 0), '1', '1.05 @ 0');
|
|
17 |
|
|
18 |
is($::form->round_amount(1.045, 2), '1.05', '1.045 @ 2');
|
|
19 |
is($::form->round_amount(1.045, 1), '1', '1.045 @ 1');
|
|
20 |
is($::form->round_amount(1.045, 0), '1', '1.045 @ 0');
|
|
21 |
|
|
22 |
is($::form->round_amount(33.675, 2), '33.68', '33.675 @ 2');
|
|
23 |
is($::form->round_amount(33.675, 1), '33.7', '33.675 @ 1');
|
|
24 |
is($::form->round_amount(33.675, 0), '34', '33.675 @ 0');
|
|
25 |
|
|
26 |
is($::form->round_amount(44.9 * 0.75, 2), '33.68', '44.9 * 0.75 @ 2');
|
|
27 |
is($::form->round_amount(44.9 * 0.75, 1), '33.7', '44.9 * 0.75 @ 1');
|
|
28 |
is($::form->round_amount(44.9 * 0.75, 0), '34', '44.9 * 0.75 @ 0');
|
|
29 |
|
|
30 |
is($::form->round_amount(149.175, 2), '149.18', '149.175 @ 2');
|
|
31 |
is($::form->round_amount(149.175, 1), '149.2', '149.175 @ 1');
|
|
32 |
is($::form->round_amount(149.175, 0), '149', '149.175 @ 0');
|
|
33 |
|
|
34 |
is($::form->round_amount(198.90 * 0.75, 2), '149.18', '198.90 * 0.75 @ 2');
|
|
35 |
is($::form->round_amount(198.90 * 0.75, 1), '149.2', '198.90 * 0.75 @ 1');
|
|
36 |
is($::form->round_amount(198.90 * 0.75, 0), '149', '198.90 * 0.75 @ 0');
|
|
37 |
|
|
38 |
# Negative values
|
|
39 |
is($::form->round_amount(-1.05, 2), '-1.05', '-1.05 @ 2');
|
|
40 |
is($::form->round_amount(-1.05, 1), '-1.1', '-1.05 @ 1');
|
|
41 |
is($::form->round_amount(-1.05, 0), '-1', '-1.05 @ 0');
|
|
42 |
|
|
43 |
is($::form->round_amount(-1.045, 2), '-1.05', '-1.045 @ 2');
|
|
44 |
is($::form->round_amount(-1.045, 1), '-1', '-1.045 @ 1');
|
|
45 |
is($::form->round_amount(-1.045, 0), '-1', '-1.045 @ 0');
|
|
46 |
|
|
47 |
is($::form->round_amount(-33.675, 2), '-33.68', '33.675 @ 2');
|
|
48 |
is($::form->round_amount(-33.675, 1), '-33.7', '33.675 @ 1');
|
|
49 |
is($::form->round_amount(-33.675, 0), '-34', '33.675 @ 0');
|
|
50 |
|
|
51 |
is($::form->round_amount(-44.9 * 0.75, 2), '-33.68', '-44.9 * 0.75 @ 2');
|
|
52 |
is($::form->round_amount(-44.9 * 0.75, 1), '-33.7', '-44.9 * 0.75 @ 1');
|
|
53 |
is($::form->round_amount(-44.9 * 0.75, 0), '-34', '-44.9 * 0.75 @ 0');
|
|
54 |
|
|
55 |
is($::form->round_amount(-149.175, 2), '-149.18', '-149.175 @ 2');
|
|
56 |
is($::form->round_amount(-149.175, 1), '-149.2', '-149.175 @ 1');
|
|
57 |
is($::form->round_amount(-149.175, 0), '-149', '-149.175 @ 0');
|
|
58 |
|
|
59 |
is($::form->round_amount(-198.90 * 0.75, 2), '-149.18', '-198.90 * 0.75 @ 2');
|
|
60 |
is($::form->round_amount(-198.90 * 0.75, 1), '-149.2', '-198.90 * 0.75 @ 1');
|
|
61 |
is($::form->round_amount(-198.90 * 0.75, 0), '-149', '-198.90 * 0.75 @ 0');
|
|
62 |
|
|
63 |
done_testing;
|
|
64 |
|
|
65 |
1;
|
round_amount: Fix für falsches Runden bestimmter Werte
Gewisse Werte wie z.B. 33,675 wurden bei 2 Stellen falsch gerundet,
nämlich auf 33,67 anstelle von 33,68. Bei anderen Werten hingegen
funktionierte es (beispielsweise 149,175 @ 2 → 149,18).
Grund war, dass durch das Addieren von 0.5 wieder Fließkommaberechnung
und damit die Ungenauigkeit der Präsentation der IEEE-Fließkommazahlen
ins Spiel kommt. Das anschließende int() schneidet dann die
Fließkommazahl falsch ab, ungefähr so:
- Initial: 33,675
- Linksshift um 2 Dezimalstellen, also * 100: 3367,5
- Dann + 0.5 und truncate, hier passierts: +0.5 =
3367,499999999999999999999958 (auch wenn Perl das in der Ausgabe als
3368 darstellen würde) oder so, davon int() ergibt nun mal 3367 vor
anschließendem Rechtsshift um 2 Dezimalstellen
Lösung ist, bis auf das Links-/Rechtsshiften um die Dezimalstellen gar
keine Fließkommaberechnung zu verwenden. Eine Variante ist, eine Stelle
mehr zu shiften als man an Genauigkeit will, dann 5 zu addieren und
anschließend auf das nächst kleinere Vielfache von 10 zu
reduzieren (durch simples Abziehen vom Modulo 10).
Um die Logik leicht einfacher zu halten, wird das Vorzeichen anfangs
ermittelt und ab dann nur noch mit dem Absolutwert der Zahl
gerechnet. Das ursprüngliche Vorzeichen wird erst nach dem erneuten
Rechtsshift, also ganz am Schluss der Berechnung, wieder hergestellt.