Thread Kaufmännisch korrekt runden (67 answers)
Opened by bianca at 2009-12-11 07:14

topeg
 2009-12-12 01:40
#129240 #129240
User since
2006-07-10
2611 Artikel
BenutzerIn

user image
Um das etwas zu illustrieren:
Code (perl): (dl )
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#!/usr/bin/perl
use strict;
use warnings;

#########################################################################################
#########################################################################################

sub kfmrunden_topeg
{
  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";
  #$zahl=sprintf("%.${stelle}f",$zahl);
  return $zahl+0;
}


sub neueloesung {
        my $num = shift (@_) || 0;
        my $stellen = shift (@_) || 0;
        my $rounded = '0';
        if ($stellen >= 0 && $stellen <= 9 && !($num =~ /[^-\.0-9]/)) {
                $rounded = int ($num * (10 ** $stellen) + ($num < 0 ? -0.5 : 0.5) ) / 10 ** $stellen;
        }
        return $rounded;
}
#########################################################################################
#########################################################################################

my @subs=('kfmrunden_topeg','neueloesung');

#########################################################################################
#########################################################################################
sub tests
{
  my $sub=shift;
  $sub=\&$sub;
 
  my $cnt=0;
  for my $i (0..200)
  {
    my $stellen=9;    
    my $wert="0.".substr(("0"x($stellen+1)).($i*5),-($stellen+1),($stellen+1));
    $cnt++ if(($i*5)%10);
    my $erwartet = "0.".substr(("0"x($stellen+1)).($cnt*10),-($stellen+1),($stellen+1)) +0;
    my $gerundet=$sub->($wert,$stellen);
    printout($wert,$erwartet,$gerundet,$stellen);
  };
  print "#"x80,"\n";

  $cnt=1;
  my $erwartet=0.01;
  my $wert=0.005;
  for my $i (0..200)
  {
    my $stellen=2;
    my $gerundet=$sub->($wert,$stellen);
    printout($wert,$erwartet,$gerundet,$stellen);

    $wert+=0.005;
    if($cnt==2)
    {
      $erwartet+=0.01;
      $cnt=0;
    }
    $cnt++;
  };
  print "#"x80,"\n";
}

sub printout
{
  my $wert=shift;
  my $soll=shift;
  my $ist=shift;
  my $stellen=shift;
  
  $soll=sprintf("%0.${stellen}f",$soll);
  $ist=sprintf("%0.${stellen}f",$ist);

  my $space = '.' x 25;

  print "\'$wert\'" . substr ($space,0,25 - length ($wert)) . "auf $stellen Stelle(n): \'$ist\'" . substr ($space,0,25 - length ($ist)) . ($soll == $ist ? ' OK' : " FEHLER! Erwartet \'$soll\'") . "\n";
}

#########################################################################################
#########################################################################################

for my $sub (@subs)
{
  print "SUB $sub\n";
  tests($sub);
  print "#"x80,"\n";
  print "#"x80,"\n";
  print "#"x80,"\n";
}


Das Interessante heraus gepickt:
Code: (dl )
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
SUB neueloesung
'0.0000000000'.............auf 9 Stelle(n): '0.000000000'.............. OK
'0.0000000005'.............auf 9 Stelle(n): '0.000000001'.............. OK
'0.0000000010'.............auf 9 Stelle(n): '0.000000001'.............. OK
'0.0000000015'.............auf 9 Stelle(n): '0.000000002'.............. OK
'0.0000000020'.............auf 9 Stelle(n): '0.000000002'.............. OK
'0.0000000025'.............auf 9 Stelle(n): '0.000000003'.............. OK
'0.0000000030'.............auf 9 Stelle(n): '0.000000003'.............. OK
'0.0000000035'.............auf 9 Stelle(n): '0.000000004'.............. OK
'0.0000000040'.............auf 9 Stelle(n): '0.000000004'.............. OK
'0.0000000045'.............auf 9 Stelle(n): '0.000000005'.............. OK
'0.0000000050'.............auf 9 Stelle(n): '0.000000005'.............. OK
'0.0000000055'.............auf 9 Stelle(n): '0.000000006'.............. OK
'0.0000000060'.............auf 9 Stelle(n): '0.000000006'.............. OK
'0.0000000065'.............auf 9 Stelle(n): '0.000000007'.............. OK
'0.0000000070'.............auf 9 Stelle(n): '0.000000007'.............. OK
'0.0000000075'.............auf 9 Stelle(n): '0.000000007'.............. FEHLER! Erwartet '0.000000008'
'0.0000000080'.............auf 9 Stelle(n): '0.000000008'.............. OK
'0.0000000085'.............auf 9 Stelle(n): '0.000000009'.............. OK
...
'0.0000000305'.............auf 9 Stelle(n): '0.000000031'.............. OK
'0.0000000310'.............auf 9 Stelle(n): '0.000000031'.............. OK
'0.0000000315'.............auf 9 Stelle(n): '0.000000031'.............. FEHLER! Erwartet '0.000000032'
'0.0000000320'.............auf 9 Stelle(n): '0.000000032'.............. OK
'0.0000000325'.............auf 9 Stelle(n): '0.000000033'.............. OK
...
################################################################################
'0.005'....................auf 2 Stelle(n): '0.01'..................... OK
'0.01'.....................auf 2 Stelle(n): '0.01'..................... OK
'0.015'....................auf 2 Stelle(n): '0.02'..................... OK
'0.02'.....................auf 2 Stelle(n): '0.02'..................... OK
'0.025'....................auf 2 Stelle(n): '0.03'..................... OK
'0.03'.....................auf 2 Stelle(n): '0.03'..................... OK
'0.035'....................auf 2 Stelle(n): '0.04'..................... OK
'0.04'.....................auf 2 Stelle(n): '0.04'..................... OK
'0.045'....................auf 2 Stelle(n): '0.05'..................... OK
'0.05'.....................auf 2 Stelle(n): '0.05'..................... OK
'0.055'....................auf 2 Stelle(n): '0.05'..................... FEHLER! Erwartet '0.06'
'0.06'.....................auf 2 Stelle(n): '0.06'..................... OK
'0.065'....................auf 2 Stelle(n): '0.06'..................... FEHLER! Erwartet '0.07'
'0.07'.....................auf 2 Stelle(n): '0.07'..................... OK
...


EDIT: Kleinen Fehler beseitigt der das erkennen bestimmter Zahlen in meiner Rundungs-Funktion verhinderte.
Last edited: 2009-12-12 22:20:28 +0100 (CET)

View full thread Kaufmännisch korrekt runden