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