Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Kaufmännisch runden

155 views
Skip to first unread message

Michael Döring

unread,
Sep 7, 2000, 11:17:08 AM9/7/00
to
Hi!

Hier nun meine Routine zum kaufmännischen Runden mit Perl.
Anlaß: SPRINTF von Perl ist unzuverlässig, schönes Beispiel ist, den Wert
1.345 mit sprintf auf 2 Stellen zu "runden".

Bitte bedient Euch nach Belieben und laßt mir Verbesserungen bitte zukommen:
(ein konkretes Problem habe ich noch: die Nachkommastellen werden größer 3
auch gruppiert. Das würde ich gern abschalten aber wie?) :-)

sub RUNDEN($;$) {

##
## Rundet einen Wert mit beliebig vielen Nachkommastellen KAUFMÄNNISCH(!)
## auf einen Wert mit der angegebenen Zahl Nachkommastellen (max. 3).
## Kaufmännisch heißt im Beispiel mit zwei Stellen:
## 3.45 bleibt 3.45
## aus 3.4510000000001 bis 3.4549999999999 wird 3,45
## aus 3.4550000000001 bis 3.4599999999999 wird 3,46
##
## Außerdem werden Dezimalpunkte eingefügt und aus dem
## Dezimalpunkt wird ein Komma gemacht.
## z.B. aus 1234.56 wird 1.234,56 bei 2 Stellen
##
## Die Nachkommastellen werden mit 0 aufgefüllt wenn
## durch den Wert die angegebene Zahl nicht erreicht wird,
## z.B. aus 3.4 wird 3,400 bei 3 Stellen
##
## Wird aufgerufen mit
## $return = &RUNDEN($wert,$stellen);
## wobei $wert die zu rundende Zahl ist
## und $stellen die Anzahl der zu rundenden Nachkommastellen ist
##
## $return enthält dann den gerundeten Wert von $wert
## oder 0 bei Mißerfolg
##

my ($val,$dec) = @_;
return 0 if ((!defined $val) || (!defined $dec) || ($val=~ /[^-0-9\.]/) ||
($dec=~ /[^-0-9]/) || ($dec<0) || ($dec>3));
$val = (($val + (0.5/(10**$dec)))*100)/100; # mathematisch aufrunden
my $res = int($val*(10**$dec))/(10**$dec); # Nachkommastellen abschneiden
$res =~ y/./,/; # ordentlich formatieren
1 while $res =~ s/(\d)(\d\d\d)\b/$1.$2/; # Grueppchen bilden
return $res;
}

Gruß
M.D.

Lukas Ertl

unread,
Sep 12, 2000, 5:38:58 PM9/12/00
to
Michael Döring <mic...@michael-doering.de> wrote:
>Hi!
>
>Hier nun meine Routine zum kaufmännischen Runden mit Perl.
>Anlaß: SPRINTF von Perl ist unzuverlässig, schönes Beispiel ist, den Wert
>1.345 mit sprintf auf 2 Stellen zu "runden".

Vielleicht ist zu diesem Thema auch ein Blick auf Math::Currency wert.

lg,
le

--
"To stop the drip, turn cock to right."
-- On the faucet in a Finnish washroom.

Thoren Johne

unread,
Sep 13, 2000, 3:00:00 AM9/13/00
to
Michael Döring <mic...@michael-doering.de> wrote in message
news:8p8bi6$car$1...@news.netcologne.de...

> Hier nun meine Routine zum kaufmännischen Runden mit Perl.
> Anlaß: SPRINTF von Perl ist unzuverlässig, schönes Beispiel ist,
> den Wert 1.345 mit sprintf auf 2 Stellen zu "runden".
>
> Bitte bedient Euch nach Belieben und laßt mir Verbesserungen bitte
> zukommen: (ein konkretes Problem habe ich noch: die Nachkommastellen
> werden größer 3 auch gruppiert. Das würde ich gern abschalten aber
> wie?) :-)

[useless code snipped]

sorry, aber das versteh ich jetzt nicht ganz. was bitte ist an
sprintf unzuverlässig?

#!/usr/local/bin/perl -w
use strict;

my $zahl = 1.345;

my $rundzahl = sprintf "%.2f", $zahl;
print $rundzahl;

ergibt bei mir (Perl 5.00503 und 5.6):
1.35

hätte ich etwas anderes erwarten sollen?

übrigens: für $zahl = 1.343 bekomme ich:
1.34

voller fragen
thoren
8#X

--
----------------------------------------------------------------------
Thoren Johne - 8#X - tho...@southern-division.com
Southern Division Classic Bikes - www.southern-division.com

Dietmar Staab

unread,
Sep 13, 2000, 3:00:00 AM9/13/00
to
In article <8pol0c$asa$12$1...@news.t-online.com>, "Thoren Johne"

<tho...@southern-division.com> wrote:
> sorry, aber das versteh ich jetzt nicht ganz. was bitte ist an sprintf
> unzuverlässig?

Ich würde es auch nicht unzuverlässig nennen, aber schau mal unter perldoc
-q round - da steht das u.a. mit kaufmännischen Anwendungen, daß da nicht
immer das raus kommt, was man erwartet. Nützlich ist in diesem
Zusammenhang das Currency-Modul (wurde hier von Lukas bereits angemerkt).



> #!/usr/local/bin/perl -w
> use strict;
>
> my $zahl = 1.345;
>
> my $rundzahl = sprintf "%.2f", $zahl; print $rundzahl;
>
> ergibt bei mir (Perl 5.00503 und 5.6):
> 1.35

bei mir ergibt das unter 5.00503 den Wert 1.34; erst bei 1.236 wird da
aufgerundet.

> voller fragen thoren
> 8#X

fragen minimiert? Dietmar


Jürgen Exner

unread,
Sep 13, 2000, 3:00:00 AM9/13/00
to
"Thoren Johne" <tho...@southern-division.com> wrote in message
news:8pol0c$asa$12$1...@news.t-online.com...

> sorry, aber das versteh ich jetzt nicht ganz. was bitte ist an
> sprintf unzuverlässig?
[...]

> my $zahl = 1.345;
>
> my $rundzahl = sprintf "%.2f", $zahl;
> print $rundzahl;
>
> ergibt bei mir (Perl 5.00503 und 5.6):
> 1.35
>
> hätte ich etwas anderes erwarten sollen?

Nach DIN wird eine *exakte* 5 abgerundet, d.h. in diesem Beispiel muesste
1.345 zu 1.34 gerundet werden. Nur falls die 5 nicht exakt ist (d.h. es gibt
noch weitere Stellen ungleich 0) oder ihrerseits durch abrunden entstanden
ist wird aufgerundet.

jue

Thoren Johne

unread,
Sep 13, 2000, 3:00:00 AM9/13/00
to
Dietmar Staab <dietma...@t-online.de> wrote in message
news:8ponhv$b5d$13$1...@news.t-online.com...

> In article <8pol0c$asa$12$1...@news.t-online.com>, "Thoren Johne"
> <tho...@southern-division.com> wrote:
> > sorry, aber das versteh ich jetzt nicht ganz. was bitte ist an sprintf
> > unzuverlässig?
>
> Ich würde es auch nicht unzuverlässig nennen, aber schau mal unter perldoc
> -q round - da steht das u.a. mit kaufmännischen Anwendungen, daß da nicht
> immer das raus kommt, was man erwartet. Nützlich ist in diesem
> Zusammenhang das Currency-Modul (wurde hier von Lukas bereits angemerkt).

:) schon gelesen... danke trotzdem für den hinweis ;)

naja... ich kenne das modul nicht, arbeite aber eigentlich bei
monitären beträgen grundsätzlich mit ganzzahligen pfenningwerten und
rechne nur für die ausgabe auf FP DM beträge um.

aufgrund der generellen problematik der limitierten darstellung von
brüchen auf binär arbeitenden computern scheint mir das auch die
einzig 'brauchbare' lösung zu sein.

manche scheinen probleme damit zu haben so vorzugehen -
ist wohl gewöhnungs/erfahrungssache ;)

gruß

Thoren Johne

unread,
Sep 14, 2000, 3:00:00 AM9/14/00
to
Jürgen Exner <ju...@deja.com> wrote in message
news:39bf...@news.microsoft.com...

> "Thoren Johne" <tho...@southern-division.com> wrote in message
> news:8pol0c$asa$12$1...@news.t-online.com...
> Nach DIN wird eine *exakte* 5 abgerundet, d.h. in diesem Beispiel muesste
> 1.345 zu 1.34 gerundet werden. Nur falls die 5 nicht exakt ist (d.h. es
gibt
> noch weitere Stellen ungleich 0) oder ihrerseits durch abrunden entstanden
> ist wird aufgerundet.

nun... dann scheint das programm vom Michael Döring aber auch nicht nach
DIN zu runden, denn damit bekomme ich exakt den gleichen wert zurück
wie bei sprintf und $zahl = 1.345;

in beiden fällen ist das ergebnis 1.35

Michael Döring

unread,
Sep 15, 2000, 3:00:00 AM9/15/00
to
"Thoren Johne" <tho...@southern-division.com> schrieb im Newsbeitrag
news:8pr90i$6kc$12$1...@news.t-online.com...

> Jürgen Exner <ju...@deja.com> wrote in message
> news:39bf...@news.microsoft.com...
> > "Thoren Johne" <tho...@southern-division.com> wrote in message
> > news:8pol0c$asa$12$1...@news.t-online.com...
> > Nach DIN wird eine *exakte* 5 abgerundet, d.h. in diesem Beispiel
muesste
> > 1.345 zu 1.34 gerundet werden. Nur falls die 5 nicht exakt ist (d.h. es
> gibt
> > noch weitere Stellen ungleich 0) oder ihrerseits durch abrunden
entstanden
> > ist wird aufgerundet.
>
> nun... dann scheint das programm vom Michael Döring aber auch nicht nach
> DIN zu runden, denn damit bekomme ich exakt den gleichen wert zurück
> wie bei sprintf und $zahl = 1.345;
>
> in beiden fällen ist das ergebnis 1.35

Mit ActivePerl 5.004_02 für Windows halt eben nicht, da kommt bei SPRINTF
leider 1.34 raus.

--
Michael Döring, 53840 Troisdorf
Tel 02241 9781-97 -- Fax -96 -- eMail in...@mikdoe.com -- ICQ 12860386


Thoren Johne

unread,
Sep 15, 2000, 3:00:00 AM9/15/00
to
Michael Döring <mic...@michael-doering.de> wrote in message
news:8psv49$gkb$2...@news.netcologne.de...

> "Thoren Johne" <tho...@southern-division.com> schrieb im Newsbeitrag
> news:8pr90i$6kc$12$1...@news.t-online.com...
> > in beiden fällen ist das ergebnis 1.35
>
> Mit ActivePerl 5.004_02 für Windows halt eben nicht, da kommt bei SPRINTF
> leider 1.34 raus.

verstehe. gottlob setze ich das schon lange nicht mehr ein ;)

Michael Döring

unread,
Sep 17, 2000, 3:00:00 AM9/17/00
to
Also, jetzt habe ich die Routine nochmal gründlich überarbeitet und jetzt
funktioniert sie auch mathematisch korrekt.

Wer noch einen Fehler findet, bekommt 100 adViews auf ....? :-)

sub RUNDEN($;$) {

##
## Rundet einen Wert mit beliebig vielen Nachkommastellen KAUFMÄNNISCH(!)

## auf einen Wert mit der angegebenen Zahl Nachkommastellen.


## Kaufmännisch heißt im Beispiel mit zwei Stellen:
## 3.45 bleibt 3.45
## aus 3.4510000000001 bis 3.4549999999999 wird 3,45
## aus 3.4550000000001 bis 3.4599999999999 wird 3,46
##
## Außerdem werden Dezimalpunkte eingefügt und aus dem
## Dezimalpunkt wird ein Komma gemacht.
## z.B. aus 1234.56 wird 1.234,56 bei 2 Stellen
##
## Die Nachkommastellen werden mit 0 aufgefüllt wenn
## durch den Wert die angegebene Zahl nicht erreicht wird,
## z.B. aus 3.4 wird 3,400 bei 3 Stellen
##
## Wird aufgerufen mit
## $return = &RUNDEN($wert,$stellen);
## wobei $wert die zu rundende Zahl ist
## und $stellen die Anzahl der zu rundenden Nachkommastellen ist
##
## $return enthält dann den gerundeten Wert von $wert
## oder 0 bei Mißerfolg
##

my ($val,$dec) = @_;
return 0 if ((!defined $val) || (!defined $dec) || ($val=~ /[^-0-9\.]/) ||

($dec=~ /[^-0-9]/) || ($dec<0) || ($dec>10));

my $neg = 0;
if ($val<0) {$val=$val*-1;$neg = 1} # Vorzeichen raus sonst stimmt die
Rechnung nicht


$val = (($val + (0.5/(10**$dec)))*100)/100; # mathematisch aufrunden
my $res = int($val*(10**$dec))/(10**$dec); # Nachkommastellen abschneiden
$res =~ y/./,/; # ordentlich formatieren

my ($vor,$nach) = split(/,/,$res); # Vor-/Nach-Komma trennen
1 while $vor =~ s/(\d)(\d\d\d)\b/$1.$2/; # Tausenderpunkte
$nach = '' if !defined $nach; # wenn keine Nachkommastellen
while (length($nach)<$dec) {$nach.='0'} # ggfs. Nullen anhängen
$vor = '-'.$vor if $neg; # ggfs. Vorzeichen wieder rein
return $dec ? "$vor,$nach" : $vor; # ggfs. zusammenbauen
}


Gruß

Thomas Klein

unread,
Sep 27, 2000, 3:00:00 AM9/27/00
to
Jürgen Exner <ju...@deja.com> schrieb in im Newsbeitrag:

> Nach DIN wird eine *exakte* 5 abgerundet, d.h. in diesem Beispiel muesste
> 1.345 zu 1.34 gerundet werden. Nur falls die 5 nicht exakt ist (d.h. es
gibt
> noch weitere Stellen ungleich 0) oder ihrerseits durch abrunden entstanden
> ist wird aufgerundet.

Welche DIN ist das? Wo finde ich die? Ich suche schon sehr lange etwas über
offizielle Rundungsregeln. Gilt dieses nur beim hier beschriebenen
kaufmännischen Runden oder überall? Hat es auch noch etwas mit einer "auf
gerade Zahl aufrunden" zu tun?

Hoffentlich kannst Du mir weiterhelfen.

Thomas Klein

0 new messages