Domanda

Come posso arrotondare un numero decimale (virgola mobile) al numero intero più vicino?

per es.

1.2 = 1
1.7 = 2
È stato utile?

Soluzione

Output di perldoc -q round

Perl ha una funzione round ()? Che dire di ceil () e floor ()? Funzioni Trig?

Ricorda che int () si riduce semplicemente verso 0 . Per arrotondare a un determinato numero di cifre, sprintf () o printf () è generalmente il più semplice itinerario.

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

Il modulo POSIX (parte della distribuzione standard Perl) implementa ceil () , floor () e una serie di altri aspetti matematici e trigonometrici funzioni.

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

In 5.000 a 5.003 perls, la trigonometria è stata eseguita nel Math :: Complex modulo. Con 5.004, il modulo Math :: Trig (parte di lo standard Perl distribuzione) implementa le funzioni trigonometriche. Internamente utilizza il Math :: Complex e alcune funzioni possono non funzionare fuori dal asse reale nel piano complesso, ad esempio il seno inverso di 2.

L'arrotondamento delle applicazioni finanziarie può avere serie implicazioni e il metodo di arrotondamento utilizzato deve essere specificato con precisione. In questi casi, probabilmente paga non fidarsi di qualsiasi arrotondamento del sistema usato da Perl, ma per implementare invece la funzione di arrotondamento è necessario te stesso.

Per capire il motivo, nota come avrai ancora un problema a metà strada alternanza:

    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

Non dare la colpa a Perl. È lo stesso di C. IEEE dice che dobbiamo fare Questo. Numeri Perl i cui valori assoluti sono numeri interi in 2 ** 31 (attivo Macchine a 32 bit) funzionerà praticamente come numeri interi matematici. Altri numeri non sono garantiti.

Altri suggerimenti

Pur non essendo in disaccordo con le complesse risposte sui marchi a metà strada e così via, per il caso d'uso più comune (e forse banale):

my $ arrotondato = int ($ float + 0,5);

Aggiorna

Se è possibile che il tuo $ float sia negativo, la seguente variazione produrrà il risultato corretto:

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

Con questo calcolo -1,4 viene arrotondato a -1 e da -1,6 a -2 e lo zero non esploderà.

Puoi utilizzare un modulo come Math :: Round :

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

O puoi farlo nel modo rozzo:

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

Se decidi di usare printf o sprintf, tieni presente che usano Arrotonda la metà al metodo pari .

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

Vedi perldoc / perlfaq :

  

Ricorda che int () si limita a troncare verso 0. Per arrotondare a   certo numero di cifre, sprintf () o printf () è di solito il   percorso più semplice.

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

Il modulo POSIX (parte della distribuzione standard Perl)   implementa ceil () , floor () e una serie di altri aspetti matematici   e funzioni trigonometriche.

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

In 5.000 a 5.003 perl, la trigonometria è stata eseguita nel modulo Math :: Complex .

     

Con 5.004, il modulo Math :: Trig (parte della distribuzione standard Perl) > implementa le funzioni trigonometriche.

     

Internamente utilizza il modulo Math :: Complex e alcune funzioni possono non funzionare   fuori dall'asse reale nel piano complesso, ad esempio il seno inverso di 2.

     

L'arrotondamento nelle applicazioni finanziarie può avere serie implicazioni e l'arrotondamento   il metodo utilizzato deve essere specificato con precisione. In questi casi, probabilmente paga non farlo   fidati di qualsiasi arrotondamento di sistema sia utilizzato da Perl, ma invece di implementare il   funzione di arrotondamento che ti serve.

     

Per capire perché, nota come avrai ancora un problema con l'alternanza a metà percorso:

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
     

Non dare la colpa a Perl. È lo stesso di C. IEEE dice che dobbiamo fare   Questo. Numeri Perl i cui valori assoluti sono numeri interi inferiori a 2 ** 31 (attivo   Macchine a 32 bit) funzionerà praticamente come numeri interi matematici.   Altri numeri non sono garantiti.

Non è necessario alcun modulo esterno.

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

foreach (@x){
  print 

Non è necessario alcun modulo esterno.

<*>

Forse mi manca il punto, ma ho pensato che fosse un modo molto più pulito di fare lo stesso lavoro.

Ciò che fa è scorrere tutti i numeri positivi nell'elemento, stampare il numero e il numero intero arrotondato nel formato menzionato. Il codice concatena il rispettivo intero positivo arrotondato solo in base ai decimali. int ($ _) sostanzialmente arrotondamento per difetto il numero, quindi ($ -int ($ )) acquisisce i decimali. Se i decimali sono (per definizione) strettamente inferiori a 0,5, arrotondare per eccesso il numero. In caso contrario, arrotondare per eccesso aggiungendo 1.

.' = '.( ( (

Non è necessario alcun modulo esterno.

<*>

Forse mi manca il punto, ma ho pensato che fosse un modo molto più pulito di fare lo stesso lavoro.

Ciò che fa è scorrere tutti i numeri positivi nell'elemento, stampare il numero e il numero intero arrotondato nel formato menzionato. Il codice concatena il rispettivo intero positivo arrotondato solo in base ai decimali. int ($ _) sostanzialmente arrotondamento per difetto il numero, quindi ($ -int ($ )) acquisisce i decimali. Se i decimali sono (per definizione) strettamente inferiori a 0,5, arrotondare per eccesso il numero. In caso contrario, arrotondare per eccesso aggiungendo 1.

-int(

Non è necessario alcun modulo esterno.

<*>

Forse mi manca il punto, ma ho pensato che fosse un modo molto più pulito di fare lo stesso lavoro.

Ciò che fa è scorrere tutti i numeri positivi nell'elemento, stampare il numero e il numero intero arrotondato nel formato menzionato. Il codice concatena il rispettivo intero positivo arrotondato solo in base ai decimali. int ($ _) sostanzialmente arrotondamento per difetto il numero, quindi ($ -int ($ )) acquisisce i decimali. Se i decimali sono (per definizione) strettamente inferiori a 0,5, arrotondare per eccesso il numero. In caso contrario, arrotondare per eccesso aggiungendo 1.

))<0.5) ? int(

Non è necessario alcun modulo esterno.

<*>

Forse mi manca il punto, ma ho pensato che fosse un modo molto più pulito di fare lo stesso lavoro.

Ciò che fa è scorrere tutti i numeri positivi nell'elemento, stampare il numero e il numero intero arrotondato nel formato menzionato. Il codice concatena il rispettivo intero positivo arrotondato solo in base ai decimali. int ($ _) sostanzialmente arrotondamento per difetto il numero, quindi ($ -int ($ )) acquisisce i decimali. Se i decimali sono (per definizione) strettamente inferiori a 0,5, arrotondare per eccesso il numero. In caso contrario, arrotondare per eccesso aggiungendo 1.

) : int(

Non è necessario alcun modulo esterno.

<*>

Forse mi manca il punto, ma ho pensato che fosse un modo molto più pulito di fare lo stesso lavoro.

Ciò che fa è scorrere tutti i numeri positivi nell'elemento, stampare il numero e il numero intero arrotondato nel formato menzionato. Il codice concatena il rispettivo intero positivo arrotondato solo in base ai decimali. int ($ _) sostanzialmente arrotondamento per difetto il numero, quindi ($ -int ($ )) acquisisce i decimali. Se i decimali sono (per definizione) strettamente inferiori a 0,5, arrotondare per eccesso il numero. In caso contrario, arrotondare per eccesso aggiungendo 1.

)+1 ); print "\n"; }

Forse mi manca il punto, ma ho pensato che fosse un modo molto più pulito di fare lo stesso lavoro.

Ciò che fa è scorrere tutti i numeri positivi nell'elemento, stampare il numero e il numero intero arrotondato nel formato menzionato. Il codice concatena il rispettivo intero positivo arrotondato solo in base ai decimali. int ($ _) sostanzialmente arrotondamento per difetto il numero, quindi ($ -int ($ )) acquisisce i decimali. Se i decimali sono (per definizione) strettamente inferiori a 0,5, arrotondare per eccesso il numero. In caso contrario, arrotondare per eccesso aggiungendo 1.

Quanto segue arrotonderà i numeri positivi o negativi a una determinata posizione decimale:

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

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

Di seguito è riportato un esempio di cinque diversi modi per sommare i valori. Il primo è un modo ingenuo per eseguire la somma (e non riesce). Il secondo tenta di utilizzare sprintf () , ma anche questo fallisce. Il terzo usa sprintf () mentre gli ultimi due (4 ° e 5 °) usano floor ($ value + 0,5) .

 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

Nota che floor ($ value + 0,5) può essere sostituito con int ($ value + 0.5) per rimuovere la dipendenza da POSIX .

I numeri negativi possono aggiungere alcune stranezze di cui le persone devono essere a conoscenza.

Gli approcci in stile

printf ci forniscono numeri corretti, ma possono comportare delle visualizzazioni dispari. Abbiamo scoperto che questo metodo (a mio avviso, stupidamente) inserisce un segno - se dovrebbe o non dovrebbe o meno. Ad esempio, -0,01 arrotondato al primo decimale restituisce un -0,0, anziché solo 0. Se hai intenzione di seguire l'approccio di stile printf e sai che non vuoi un decimale, usa % d e non % f (quando hai bisogno di decimali, è quando il display diventa traballante).

Mentre è corretto e per la matematica non è un grosso problema, per la visualizzazione sembra strano mostrare qualcosa come " -0.0 " ;.

Per il metodo int, i numeri negativi possono cambiare ciò che si desidera di conseguenza (anche se ci sono alcuni argomenti che possono essere fatti, sono corretti).

Il int + 0.5 causa problemi reali con numeri negativi, a meno che tu non voglia che funzioni in questo modo, ma immagino che la maggior parte delle persone non lo faccia. -0.9 probabilmente dovrebbe arrotondare a -1, non a 0. Se sai che vuoi che il negativo sia un soffitto piuttosto che un pavimento, puoi farlo in una riga, altrimenti potresti voler usare il metodo int con un minore modifica (questo ovviamente funziona solo per recuperare numeri interi:

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

La mia soluzione per 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 );

Se ti preoccupi solo di ottenere un valore intero da un numero intero in virgola mobile (ovvero 12347.9999 o 54321.0001), questo approccio (preso in prestito e modificato dall'alto) farà il trucco:

my $rounded = floor($float + 0.1); 
cat table |
  perl -ne '/\d+\s+(\d+)\s+(\S+)/ && print "".**int**(log($1)/log(2))."\t$2\n";' 
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top