Frage

Wie kann ich Runden Sie eine Dezimalzahl (Gleitkommazahl) auf die nächste ganze Zahl?

z.B.

1.2 = 1
1.7 = 2
War es hilfreich?

Lösung

Leistung von perldoc -q round

Macht Perl haben eine Funktion round ()?Was ist ceil() und floor()?Trig-Funktionen?

Denken Sie daran, dass int() lediglich schneidet in Richtung 0.Für die Rundung auf eine bestimmte Anzahl von Ziffern, sprintf() oder printf() ist in der Regel die einfachste route.

    printf("%.3f", 3.1415926535);       # prints 3.142

Die POSIX Modul - (Teil der standard-Perl-distribution) implementiert ceil(), floor(), und eine Reihe von anderen mathematischen und trigonometrischen Funktionen.

    use POSIX;
    $ceil   = ceil(3.5);                        # 4
    $floor  = floor(3.5);                       # 3

In 5.000 bis 5.003 perls, Trigonometrie gemacht wurde Math::Complex Modul.Mit 5.004, die Math::Trig Modul - (Teil der standard-Perl Verteilung) führt die trigonometrischen Funktionen.Intern verwendet die Math::Complex Modul, und einige Funktionen kann ausbrechen aus dem reellen Achse in der komplexen Ebene, zum Beispiel den inversen Sinus von 2.

Rundung in Finanz-Anwendungen können schwerwiegende Folgen haben, und die Rundungsmethode verwendet, sollte genau angegeben werden.In diese Fällen, wahrscheinlich lohnt es sich nicht zu trauen, was die Rundung wird verwendet von Perl, sondern stattdessen implementieren Sie die Runden-Funktion, die Sie benötigen selbst.

Um zu sehen, warum, zu bemerken, wie Sie immer noch ein Problem haben, auf halbem Weg-Punkt Wechsel:

    for ($i = 0; $i < 1.01; $i += 0.05) { printf "%.1f ",$i}

    0.0 0.1 0.1 0.2 0.2 0.2 0.3 0.3 0.4 0.4 0.5 0.5 0.6 0.7 0.7
    0.8 0.8 0.9 0.9 1.0 1.0

Nicht die Schuld Perl.Es ist die gleiche wie in C.IEEE sagt, wir haben zu tun diese.Perl zahlen, deren absolute Werte sind Ganzzahlen unter 2**31 (auf 32-bit-Maschinen) funktionieren so ziemlich wie mathematische Ganzzahlen.Andere zahlen sind nicht garantiert werden.

Andere Tipps

Während die komplexen Antworten etwa auf halbem Weg Marken nicht andere Meinung und so weiter, für die häufiger (und möglicherweise trivial) Use-Case:

my $rounded = int($float + 0.5);

UPDATE

Wenn es möglich ist, für Ihre $float negativ zu sein, die folgende Variante wird das richtige Ergebnis produzieren:

my $rounded = int($float + $float/abs($float*2 || 1));

Mit dieser Berechnung -1,4 auf -1 gerundet und -1,6 bis -2 und Null wird nicht explodieren.

Sie können entweder ein Modul wie verwenden Math :: Round :

use Math::Round;
my $rounded = round( $float );

Oder Sie können es die rohe Art und Weise tun:

my $rounded = sprintf "%.0f", $float;

Wenn Sie sich entscheiden printf oder sprintf zu verwenden, beachten Sie, dass sie die Rund die Hälfte sogar Verfahren.

foreach my $i ( 0.5, 1.5, 2.5, 3.5 ) {
    printf "$i -> %.0f\n", $i;
}
__END__
0.5 -> 0
1.5 -> 2
2.5 -> 2
3.5 -> 4

Siehe perldoc / perlfaq :

  

Beachten Sie, dass int() lediglich in Richtung 0. kürzt, um eine für die Rundung   bestimmte Anzahl von Ziffern, sprintf() oder printf() ist in der Regel der   einfachste Weg.

 printf("%.3f",3.1415926535);
 # prints 3.142
     

Das POSIX Modul (Teil der Standard-Perl-Distribution)   implementiert ceil(), floor(), und eine Reihe von anderen mathematischen   und trigonometrische Funktionen.

use POSIX;
$ceil  = ceil(3.5); # 4
$floor = floor(3.5); # 3
     

In 5,000-5,003 perls, Trigonometrie im Math::Complex Modul durchgeführt wurde.

     

5.004, das Math::Trig Modul (Teil der Standard-Perl-Verteilung)> implementiert die trigonometrischen Funktionen.

     

Intern verwendet es die Math::Complex Modul und einige Funktionen können brechen   aus der realen Achse in der komplexen Ebene, beispielsweise dem inversen Sinus von 2.

     

Rounding in Finanzanwendungen können schwerwiegende Folgen haben, und die Rundung   Verfahren verwendet wird, sollte genau festgelegt werden. In diesen Fällen lohnt es sich wahrscheinlich nicht um   Vertrauen Welches System Abrundung wird von Perl verwendet wird, sondern stattdessen implementieren die   Rundungsfunktion müssen Sie sich selbst.

     

Um zu sehen, warum darauf, wie Sie immer noch ein Problem auf halben Weg-Punkt-Wechsel haben werden:

for ($i = 0; $i < 1.01; $i += 0.05)
{
   printf "%.1f ",$i
}

0.0 0.1 0.1 0.2 0.2 0.2 0.3 0.3 0.4 0.4 0.5 0.5 0.6 0.7 0.7 0.8 0.8 0.9 0.9 1.0 1.0
     

Sie nicht Perl schuld. Es ist das gleiche wie in C. IEEE sagt, wir haben zu tun   diese. Perl Zahlen, deren absolute Werte sind ganze Zahlen unter 2 ** 31 (auf   32-Bit-Maschinen) wird ziemlich viel wie mathematische Zahlen arbeiten.   Andere Zahlen sind nicht garantiert.

Sie benötigen keine externe Modul.

$x[0] = 1.2;
$x[1] = 1.7;

foreach (@x){
  print $_.' = '.( ( ($_-int($_))<0.5) ? int($_) : int($_)+1 );
  print "\n";
}

Ich fehlen möglicherweise Ihren Standpunkt, aber ich dachte, das war viel sauberer Weg, um die gleiche Arbeit.

Was dieses tut, ist ein Spaziergang durch jede positive Zahl in das element, drucken Sie die Anzahl und die abgerundete ganze Zahl in dem format, das Sie erwähnt.Der code verkettet jeweiligen gerundet positive ganze Zahl ist nur auf der Grundlage der Dezimalstellen.int($_) grundsätzlich Runde-down die Zahl so ($-int($)) erfasst die Nachkommastellen.Wenn die Dezimalstellen sind (per definition) strikt kleiner als 0,5, rund-um-die Nummer.Wenn nicht, round-up durch hinzufügen 1.

Im Folgenden wird rund um positive oder negative Zahlen zu einem bestimmten Dezimalstelle:

sub round ()
{
    my ($x, $pow10) = @_;
    my $a = 10 ** $pow10;

    return (int($x / $a + (($x < 0) ? -0.5 : 0.5)) * $a);
}

Es folgt eine Stichprobe von fünf verschiedenen Arten Werte zu summieren. Die erste ist eine naive Weise die Summation (und nicht) durchzuführen. Der zweite versucht sprintf() zu verwenden, aber es scheitert auch. Die dritte Einsatz sprintf() erfolgreich, während die beiden letzten (4. und 5.) floor($value + 0.5) verwenden.

 use strict;
 use warnings;
 use POSIX;

 my @values = (26.67,62.51,62.51,62.51,68.82,79.39,79.39);
 my $total1 = 0.00;
 my $total2 = 0;
 my $total3 = 0;
 my $total4 = 0.00;
 my $total5 = 0;
 my $value1;
 my $value2;
 my $value3;
 my $value4;
 my $value5;

 foreach $value1 (@values)
 {
      $value2 = $value1;
      $value3 = $value1;
      $value4 = $value1;
      $value5 = $value1;

      $total1 += $value1;

      $total2 += sprintf('%d', $value2 * 100);

      $value3 = sprintf('%1.2f', $value3);
      $value3 =~ s/\.//;
      $total3 += $value3;

      $total4 += $value4;

      $total5 += floor(($value5 * 100.0) + 0.5);
 }

 $total1 *= 100;
 $total4 = floor(($total4 * 100.0) + 0.5);

 print '$total1: '.sprintf('%011d', $total1)."\n";
 print '$total2: '.sprintf('%011d', $total2)."\n";
 print '$total3: '.sprintf('%011d', $total3)."\n";
 print '$total4: '.sprintf('%011d', $total4)."\n";
 print '$total5: '.sprintf('%011d', $total5)."\n";

 exit(0);

 #$total1: 00000044179
 #$total2: 00000044179
 #$total3: 00000044180
 #$total4: 00000044180
 #$total5: 00000044180

Beachten Sie, dass floor($value + 0.5) mit int($value + 0.5) ersetzt werden, um die Abhängigkeit von POSIX zu entfernen.

Negative Zahlen können einige Macken hinzufügen, dass die Menschen sich bewusst sein müssen.

printf-Stil Ansätze geben uns richtige Zahlen, aber sie können in einigen ungeradeen Displays führen. Wir haben herausgefunden, dass dieses Verfahren (meiner Meinung nach, dummerweise) bringt ein - Zeichen, ob es soll oder nicht. Zum Beispiel -0,01 gerundet auf eine Dezimalstelle gibt ein -0,0, anstatt nur 0. Wenn Sie gehen, um den printf Stil Ansatz zu tun, und Sie wissen, Sie wollen keine Nachkommastelle, Verwendung %d und nicht %f (wenn Sie Dezimalzahlen benötigen, es ist, wenn das Display wackelig wird).

Während es richtig und für Mathematik ist keine große Sache, für die Anzeige es einfach seltsam sieht so etwas wie „-0,0“ zeigt.

Für die int Methode können negative Zahlen ändern, was Sie als Ergebnis wollen (obwohl es einige Argumente, die gemacht werden können, sie korrekt sind).

Die int + 0.5 verursacht echte Probleme mit -negativen Zahlen, wenn Sie es wünschen, so zu arbeiten, aber ich glaube, die meisten Menschen nicht. -0,9 sollte wohl rund -1, nicht 0. Wenn Sie wissen, dass Sie eine negative wollen eine Decke sein, anstatt ein Boden, dann können Sie es in Einzeiler tun, sonst könnten Sie die int-Methode mit einem Minderjährigen verwenden Modifikation (das funktioniert natürlich nur, wieder ganze Zahlen zu erhalten:

my $var = -9.1;
my $tmpRounded = int( abs($var) + 0.5));
my $finalRounded = $var >= 0 ? 0 + $tmpRounded : 0 - $tmpRounded;

Meine Lösung für sprintf

if ($value =~ m/\d\..*5$/){
    $format =~ /.*(\d)f$/;
    if (defined $1){
       my $coef = "0." . "0" x $1 . "05";    
            $value = $value + $coef;    
    }
}

$value = sprintf( "$format", $value );

Wenn Sie nur besorgt sind mit immer einen ganzzahligen Wert aus einer ganzen Gleitpunktzahl (d 12347,9999 oder 54321,0001), diesen Ansatz (entlehnt und modifizierte von oben) wird es tun:

my $rounded = floor($float + 0.1); 
cat table |
  perl -ne '/\d+\s+(\d+)\s+(\S+)/ && print "".**int**(log($1)/log(2))."\t$2\n";' 
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top