Auf- und abrunden
Hirl
- perl
0 Benjamin S.0 Beate Mielke0 K@rl
0 Tom0 Tom
Kann mir vielleicht jemand einen einfachen Weg zeigen,wie ich Kommazahlen, die ich durch Berechnungen in einem Perl-Programm erhalte, auf eine bestimmte Stelle nach dem Komma auf- oder abrunden kann.
Wie man kaufmännisch rundet ist mir leider nicht bekannt. Aber mit einem Trick geht es auch per int()-Befehl.
$zahl = int($zahl + 0.5) - 0.5;
Int() gibt ja nur Ganzzahlen aus, d.h. schneidet den Komma-Wert einfach ab. Wenn man vorher die Zahl + 0.5 rechnet und danach wieder um 0.5 reduziert, erzielt man genau das gleiche Ergebnis wie bei einer kaufmännischen Rundung.
Gruß Benjamin
Hallo Benjamin,
Wie man kaufmännisch rundet ist mir leider nicht bekannt. Aber mit einem Trick geht es auch per int()-Befehl.
$zahl = int($zahl + 0.5) - 0.5;
Int() gibt ja nur Ganzzahlen aus, d.h. schneidet den Komma-Wert einfach ab. Wenn man vorher die Zahl + 0.5 rechnet und danach wieder um 0.5 reduziert, erzielt man genau das gleiche Ergebnis wie bei einer kaufmännischen Rundung.
irgendetwas kann hier nicht stimmen:
angenommen $zahl ist 10.3.
$zahl + 0.5 ist dann 10.8
int (10.8) ergibt 10
10 - 0.5 ergibt 9.5
daraus wuerde folgen, dass 10.3 gerundet 9.5 ergibt, und das kann ja nicht sein.
Viele Gruesse
Beate Mielke
Wie Beate schon angemerkt hat, paßt
$zahl = int($zahl + 0.5) - 0.5;
wohl nicht ganz ...
besser (aber noch immer nicht ideal) ist
$zahl = int($zahl + 0.5);
das ist dann kaufmännisches Runden
Als Wort zum Sonntag noch ein Zitat aus "man perlfunc":
<quote>
int EXPR
int
Returns the integer portion of EXPR. If EXPR is omitted, uses $_. You should not use this function for rounding: one because it truncates towards 0, and two because machine representations of floating point numbers can sometimes produce counterintuitive results. For example, int(-6.725/0.025) produces -268 rather than the correct -269; that's because it's really more like -268.99999999999994315658 instead. Usually, the sprintf(), printf(), or the POSIX::floor and POSIX::ceil functions will serve you better than will int().
</quote>
Prägnanter kann man es nicht ausdrücken ;-)
mit herzlichem RTFM
K@rl
Hallo K@rl
Als Wort zum Sonntag noch ein Zitat aus "man perlfunc":
<quote>
int EXPR
int
Returns the integer portion of EXPR. If EXPR is omitted, uses $_. You should not use this function for rounding: one because it truncates towards 0, and two because machine representations of floating point numbers can sometimes produce counterintuitive results. For example, int(-6.725/0.025) produces -268 rather than the correct -269; that's because it's really more like -268.99999999999994315658 instead. Usually, the sprintf(), printf(), or the POSIX::floor and POSIX::ceil functions will serve you better than will int().
</quote>
Prägnanter kann man es nicht ausdrücken ;-)mit herzlichem RTFM
Im Prinzip hast Du schon recht, nur war dies das falsche Beispiel.
Denn in diesem 'fucking manual' steht zu floor nur folgendes:
<cite POSIX>
floor
This is identical to the C function floor().
</cite>
Und was sagt mir das als _Nicht_ c-Programmierer bezüglich Funktionsparameter, Rückgabewert und Funktionsweise ???
Grüsse
Tom
Im Prinzip hast Du schon recht, nur war dies das falsche Beispiel.
Denn in diesem 'fucking manual' steht zu floor nur folgendes:<cite POSIX>
floor
This is identical to the C function floor().
</cite>Und was sagt mir das als _Nicht_ c-Programmierer bezüglich Funktionsparameter, Rückgabewert und Funktionsweise ???
ich tippe mal: Funktionsparameter eine Zahl und Rückgabe wert eine Zahl .. was anderes würde mich wundern;
zur Funktionsweise: wenn Du eine U*x Maschine hast: "man floor" eingeben (.. oder isses "man3 floor"? - hab hier eine DOS Maschine).
Ansonsten:
<cite>
Usually, the sprintf(), printf(), or the POSIX::floor and POSIX::ceil functions will serve you better
</cite>
Ther's more than one way to do it -> ich persönlich setze sprintf ein
Hi Tom!
Und was sagt mir das als _Nicht_ c-Programmierer bezüglich Funktionsparameter, Rückgabewert und Funktionsweise ???
<CITE SOURCE="Microsoft Visual C++ 5.0 Runtime Library Reference">
double floor(double x);
Calculates the floor of a value.
Function Required Header Compatibility
floor <math.h> ANSI, Win 95, Win NT
Return Value
The floor function returns a floating-point value representing the largest integer that is less than or equal to x. There is no error return.
Parameter
x Floating-point value
Example
/* FLOOR.C: This example displays the largest integers
* less than or equal to the floating-point values 2.8
* and -2.8. It then shows the smallest integers greater
* than or equal to 2.8 and -2.8.
*/
#include <math.h>
#include <stdio.h>
void main( void )
{
double y;
y = floor( 2.8 );
printf( "The floor of 2.8 is %f\n", y );
y = floor( -2.8 );
printf( "The floor of -2.8 is %f\n", y );
y = ceil( 2.8 );
printf( "The ceil of 2.8 is %f\n", y );
y = ceil( -2.8 );
printf( "The ceil of -2.8 is %f\n", y );
}
Output
The floor of 2.8 is 2.000000
The floor of -2.8 is -3.000000
The ceil of 2.8 is 3.000000
The ceil of -2.8 is -2.000000
See Also ceil, fmod
</CITE>
Ist zwar eine Microsoft-Beschreibung, da als "Compatibility" jedoch ANSI angegeben ist, sollte die Bibliothek bei jedem Ansi-kompatiblen C genauso funktionieren.
Calocybe
Hallo Hirl
Das ist doch in Perl kein Problem ...
... dachte ich, bis ich im Perl-Manual nach der Round-Funktion suchte und diese nicht fand. :-((
Nun habe ich eine solche Funktion mal selbst programmiert und stelle Sie hier zur freien Verfügung:
sub round
{
my $value = shift; # Wert, der gerundet werden soll
my $precision = int(shift); # Anzahl Stellen nach dem Komma, auf die gerundet werden soll. Muss eine Ganzzahl sein.
# Positive Ganzahlen stellen die Stellen hinter dem Komma dar,
# negative Ganzzahlen die Anzahl der signifikanten Stellen vor dem Komma.
# Speichert das Vorzeichen und setzt value auf den Absolutwert.
my $sign = 1;
if($value < 0)
{ $sign = -1; }
$value = abs($value);
# Berrechnet den Genauigkeitsfaktor
my $pFactor = 10 ** $precision;
# Rundet den Wert
$value = int(($value * $pFactor) + 0.5) / $pFactor;
# Berücksichtigt das ursprüngliche Vorzeichen
$value *= $sign;
return $value;
}
Hier der Output eines Test-Skript für diese Round-Funktion:
Runden auf Ganzahl (precision=0):
round(0.5,0) = 1
round(0.51,0) = 1
round(0.49,0) = 0
round(-0.5,0) = -1
round(-0.6,0) = -1
round(-0.4,0) = 0
round(0.0,0) = 0
round(25.34,0) = 25
round(-36.82,0) = -37
Runden auf Nachkommastellen (precision>0):
round(0.453852,1) = 0.5
round(0.453852,2) = 0.45
round(0.453852,3) = 0.454
round(0.453852,4) = 0.4539
round(0.453852,5) = 0.45385
round(-15.2853,2) = -15.29
round(2546.0127,1) = 2546
round(0.758,5) = 0.758
-> Beachte: fehlende Stellen nach dem Komma werden NICHT mit '0' aufgefüllt. Dazu müssen die sprint()- und sprintf()-Funktionen verwendet werden.
Runden auf signifikante Stellen vor dem Komma (precision<0):
round(28457,-1) = 28460
round(28457,-2) = 28500
round(28457,-3) = 28000
round(28457,-4) = 30000
round(-1473.25,-2) = -1500
round(28457.035,-8) = 0
-> Beachte: Das Runden auf mehr Stellen vor dem Komma als der Wert selber aufweist, führt zum Ergebnis '0'.
Vielleicht finde ich noch ein Workaround, um dieses Problem elegant zu lösen.
Ich hoffe, damit ein kleines Problem gelöst zu haben.
Grüsse
Tom
PS an die Forumsauslese-Redaktion: Wäre das nicht etwas, das in die FA aufgenommen werden könnte?
In welcher Form hättet Ihr den kleinen Beitrag denn gerne?
Hallo
PS an die Forumsauslese-Redaktion: Wäre das nicht etwas, das in die FA aufgenommen werden könnte?
In welcher Form hättet Ihr den kleinen Beitrag denn gerne?
Sorry, ich hab es beim durchstöbern übersehen, dass das Thema in der FA schon existiert.
Trotzdem könnte man den Beitrag um die obenstehende round-Funktion ergänzen, da die Funktion mächtiger und die Behandlung von negativen Werten korrekt ist.
Grüsse
Tom