Zahlen runden mit Math::Round

Veröffentlicht von Thomas Fahle am (Permalink)

Zahlen runden kann eine recht tückische Aufgabe sein.

Das CPAN-Modul Math::Round von Geoffrey Rommel vereinfacht diese Aufgabe erheblich.

Dieser Beitrag geht auf die Themen

  • Auf Ganze Zahlen runden
  • Auf Fließkommazahlen runden, z.B. Nachkommastellen
  • Zum nächsten Vielfachen auf- oder abrunden, z.B. Hunderter
ein.

Auf Ganze Zahlen runden

Die Prozeduren round, round_even, round_odd und round_rand runden auf Ganzzahlen (Integer) auf bzw. ab.

  • round LIST rundet zur nächsten Ganzzahl auf bzw. ab.
  • round_even LIST rundet zur nächsten Ganzzahl auf bzw. ab. Zahlen, die in der Mitte zwischen zwei Ganzzahlen liegen, werden zur nächsten geraden Zahl gerundet.
  • round_odd LIST rundet zur nächsten Ganzzahl auf bzw. ab. Zahlen, die in der Mitte zwischen zwei Ganzzahlen liegen, werden zur nächsten ungeraden Zahl gerundet.
  • round_rand LIST rundet zur nächsten Ganzzahl auf bzw. ab. Zahlen, die in der Mitte zwischen zwei Ganzzahlen liegen, werden zufällig auf- bzw. abgerundet

Beispiel: Zur nächsten Ganzzahl auf- oder abrunden:

#!/usr/bin/perl 
use strict;
use warnings;
use Math::Round qw/round/;

my @zahlen = qw /-2.5 -2.0 -1.5 -1.0 -0.5 
                 0.0 
                 0.5 1.0 1.5 2.0 2.5
                 125.3456 125.5678/;

foreach my $zahl ( @zahlen ) {
	printf("%8s wird zu %8s gerundet\n", $zahl,  round($zahl));
}

Das Programm erzeugt folgende Ausgabe:

    -2.5 wird zu       -3 gerundet
    -2.0 wird zu       -2 gerundet
    -1.5 wird zu       -2 gerundet
    -1.0 wird zu       -1 gerundet
    -0.5 wird zu       -1 gerundet
     0.0 wird zu        0 gerundet
     0.5 wird zu        1 gerundet
     1.0 wird zu        1 gerundet
     1.5 wird zu        2 gerundet
     2.0 wird zu        2 gerundet
     2.5 wird zu        3 gerundet
125.3456 wird zu      125 gerundet
125.5678 wird zu      126 gerundet

Beispiel: round_even

#!/usr/bin/perl 
use strict;
use warnings;
use Math::Round qw/round_even/;


my @zahlen = qw /-2.5 -2.0 -1.5 -1.0 -0.5 
                 0.0 
                 0.5 1.0 1.5 2.0 2.5
                 125.3456 125.5678/;

foreach my $zahl ( @zahlen ) {
	printf("%8s wird zu %8s gerundet\n", $zahl,  round_even($zahl));
}

Das Programm erzeugt folgende Ausgabe:

    -2.5 wird zu       -2 gerundet
    -2.0 wird zu       -2 gerundet
    -1.5 wird zu       -2 gerundet
    -1.0 wird zu       -1 gerundet
    -0.5 wird zu        0 gerundet
     0.0 wird zu        0 gerundet
     0.5 wird zu        0 gerundet
     1.0 wird zu        1 gerundet
     1.5 wird zu        2 gerundet
     2.0 wird zu        2 gerundet
     2.5 wird zu        2 gerundet
125.3456 wird zu      125 gerundet
125.5678 wird zu      126 gerundet

Beispiel: round_odd

#!/usr/bin/perl 
use strict;
use warnings;
use Math::Round qw/round_odd/;


my @zahlen = qw /-2.5 -2.0 -1.5 -1.0 -0.5 
                 0.0 
                 0.5 1.0 1.5 2.0 2.5
                 125.3456 125.5678/;

foreach my $zahl ( @zahlen ) {
	printf("%8s wird zu %8s gerundet\n", $zahl,  round_odd($zahl));
}

Das Programm erzeugt folgende Ausgabe:

    -2.5 wird zu       -3 gerundet
    -2.0 wird zu       -2 gerundet
    -1.5 wird zu       -1 gerundet
    -1.0 wird zu       -1 gerundet
    -0.5 wird zu       -1 gerundet
     0.0 wird zu        0 gerundet
     0.5 wird zu        1 gerundet
     1.0 wird zu        1 gerundet
     1.5 wird zu        1 gerundet
     2.0 wird zu        2 gerundet
     2.5 wird zu        3 gerundet
125.3456 wird zu      125 gerundet
125.5678 wird zu      126 gerundet

Beispiel: round_rand

#!/usr/bin/perl 
use strict;
use warnings;

use Math::Round qw/round_rand/;

# Messbereich (Anzahl der Messungen);
my $von = 1;
my $bis  = 10_000;

# Die Zahl, die gemessen/geprüft wird
my $zahl = 2.5;

# Zaehler fuer Anzahl der Messungen
my $anzahl_messungen = 0;

# Container fuer die Messergebnisse
my %messergebnis = ();

for ( $von .. $bis ) {
	my $gerundet = round_rand($zahl);
	$messergebnis{$gerundet}++;
	$anzahl_messungen++;
}

my @messwerte = keys %messergebnis;

foreach my $messwert (@messwerte) {
	print "$zahl wurde $messergebnis{$messwert} mal zu $messwert gerundet.\n";
	print "Das entspricht ", $messergebnis{$messwert} / $anzahl_messungen * 100 , "%.\n";
}

Das Programm erzeugt folgende Ausgabe:

2.5 wurde 5044 mal zu 3 gerundet.
Das entspricht 50.44%.
2.5 wurde 4956 mal zu 2 gerundet.
Das entspricht 49.56%.

Runden auf Ganzzahlen im Vergleich

Das folgende Beispiel erstellt eine kleine tabellarische Übersicht, die den Vergleich der vorgestellten Prozeduren vereinfachen soll.

#!/usr/bin/perl 
use strict;
use warnings;


use Math::Round qw/round round_even round_odd round_rand/;


my @zahlen = qw /-2.5 -2.0 -1.5 -1.0 -0.5 
                 0.0 
                 0.5 1.0 1.5 2.0 2.5
                /;

# Format für printf
my $format = '%6s %6s %10s %10s %10s';


printf("$format\n", 'Zahl', 'round', 'round_even', 'round_odd', 'round_rand');

foreach my $zahl ( @zahlen ) {
	printf("$format\n", $zahl, round($zahl), round_even($zahl), round_odd($zahl), round_rand($zahl) );
}

Das Programm erzeugt folgende Ausgabe:

  Zahl  round round_even  round_odd round_rand
  -2.5     -3         -2         -3         -3
  -2.0     -2         -2         -2         -2
  -1.5     -2         -2         -1         -2
  -1.0     -1         -1         -1         -1
  -0.5     -1          0         -1          0
   0.0      0          0          0          0
   0.5      1          0          1          1
   1.0      1          1          1          1
   1.5      2          2          1          2
   2.0      2          2          2          2
   2.5      3          2          3          2

Auf Fließkommazahlen runden

Hier bietet sich nearest(TARGET, LIST) an. nearest rundet zum Vielfachen von TARGET auf bzw. ab.

Beispiel: Auf eine bzw. zwei Nachkommastellen runden

#!/usr/bin/perl 
use strict;
use warnings;

use Math::Round qw/nearest/;

my @zahlen = qw /-2.5 -2.0 -1.5 -1.0 -0.5 
                 0.0 
                 0.5 1.0 1.5 2.0 2.5
                 125.3456 125.5678/;

my $format = '%8s %8s %8s';
printf("$format\n", 'Zahl', 'Eine NK', 'Zwei NK' );
foreach my $zahl ( @zahlen ) {
			# Eine Nachkommastelle (0.1)
			# Zwei Nachkommastellen (0.01)
	printf("$format\n", $zahl,  nearest('0.1',$zahl), nearest('0.01',$zahl) );
}

Das Programm erzeugt folgende Ausgabe:

    Zahl  Eine NK  Zwei NK
    -2.5     -2.5     -2.5
    -2.0       -2       -2
    -1.5     -1.5     -1.5
    -1.0       -1       -1
    -0.5     -0.5     -0.5
     0.0        0        0
     0.5      0.5      0.5
     1.0        1        1
     1.5      1.5      1.5
     2.0        2        2
     2.5      2.5      2.5
125.3456    125.3   125.35
125.5678    125.6   125.57

Zum nächsten Vielfachen auf- oder abrunden

Die beiden Prozeduren nlowmult und nhimult runden zum nächsten kleineren bzw. größerem Vielfachen ab bzw. auf.

  • nlowmult TARGET, LIST rundet zum nächsten kleineren Vielfachen ab.
  • nhimult TARGET, LIST rundet zum nächsten größeren Vielfachen auf.

Beispiel: Auf volle 100er auf- bzw. abrunden.

#!/usr/bin/perl 
use strict;
use warnings;

use Math::Round qw/nlowmult nhimult/;

my @zahlen = qw/ 126 176/;

# Auf volle 100er auf- bzw. abrunden
my $target = 100;

my $format = '%6s %10s %10s';

printf("$format\n", 'Zahl', 'nlowmult', 'nhimult');

foreach my $zahl (@zahlen) {
	printf("$format\n", $zahl, nlowmult($target,$zahl), nhimult($target,$zahl) );
}

Das Programm erzeugt folgende Ausgabe:

  Zahl   nlowmult    nhimult
   126        100        200
   176        100        200

Das funktioniert auch mit Vielfachen von Fließkommazahlen. Probieren Sie es einfach mal aus.

Siehe auch

Weitere Posts

Aktuelle Posts

Stay Tuned

Blog Roll

CC Lizenz

Powered By