Arrotondare un numero in virgola mobile al numero intero più vicino?


128

Come suggerisce il titolo, voglio prendere un numero in virgola mobile e arrotondarlo per difetto al numero intero più vicino. Tuttavia, se non è un intero, voglio SEMPRE arrotondare per difetto la variabile, indipendentemente da quanto sia vicina al numero intero successivo. C'è un modo per fare questo?


2
Una possibile difficoltà è che i formati a virgola mobile IEEE possono rappresentare numeri così grandi che la grandularità è maggiore di 1. Così, mentre puoi arrotondare x per difetto, arrotondare x + 1 per difetto non ti darà il risultato che ti aspetti.
dmckee --- gattino ex moderatore

Si prega di pubblicare alcuni esempi.
Ashwini Chaudhary

Risposte:


179

Semplice

print int(x)

funzionerà anche.


7
int (0,6) = 0 anziché 1
Helin Wang

39
@HelinWang Questo è esattamente ciò che OP ha chiesto.
Petr Peller

5
Questo sembra l'approccio più pitonico.
Gyan Veda

23
Questo funziona bene per i numeri positivi, ma i numeri negativi verranno arrotondati per eccesso:int(-23.3) == 23
Alex Riley

2
e non funziona per numeri oltre l'intervallo intero come 600851475143, in pratica segnalerà un errore di memoria.
Muyide Ibukun

77

Uno di questi dovrebbe funzionare:

import math
math.trunc(1.5)
> 1
math.trunc(-1.5)
> -1
math.floor(1.5)
> 1
math.floor(-1.5)
> -2

14
L'output di math.truncè un numero intero, mentre l'output di math.floorè un float.
evedovelli

6
@evedovelli: Non proprio più. type(math.floor(1.51)) -> intetype(math.trunc(1.51)) -> int dalpython 3.6.0
SKPS

4
Queste opzioni sono più esplicite di "int (x)" e quindi sono più pitoniche.
Tristan

44
x//1

L' //operatore restituisce il piano della divisione. Poiché la divisione per 1 non cambia il tuo numero, questo è equivalente a floor ma non è necessaria alcuna importazione. Appunti:

  1. Questo restituisce un float
  2. Questo arrotonda verso -∞

Bella aggiunta. int(-1.1) == -1mentre -1.1//1 == -2.0tuttavia decimal.Decimal('-1.1')//1 == decimal.Decimal('-1')(come documentato, l'affermazione 2 non è vera per decimal), quindi fare affidamento su come //si comporta non è completamente stabile, anche oggi.
Tino

28

Per ottenere risultati in virgola mobile, usa semplicemente:

round(x-0.5)

Funziona anche per i numeri negativi.


6
estremamente sofisticato cioè
Alon


9

molte persone dicono di usare int(x), e questo funziona bene per la maggior parte dei casi, ma c'è un piccolo problema. Se il risultato di OP è:

x = 1.9999999999999999

arrotonderà a

x = 2

dopo il 16 9 verrà arrotondato. Questo non è un grosso problema se sei sicuro che non ti imbatterai mai in una cosa del genere. Ma è qualcosa da tenere a mente.


17
Questo perché 1.9999999999999999è effettivamente uguale a 2.0nella rappresentazione float64 interna. I. e. è già arrotondato non appena viene analizzato in un float, poiché un float a 64 bit non può rappresentare così tante cifre significative. Puoi verificarlo con la valutazione 1.9999999999999999 == 2.0. E se sospetti che l'operazione di uguaglianza esegua un certo arrotondamento sui float, puoi confrontare la rappresentazione binaria con struct.pack("d", 1.9999999999999999) == struct.pack("d", 2.0), che è anche uguale.
blubberdiblub

4
E se questo è esattamente il tuo punto, allora non vedo cosa c'è che non va int(). Il valore è già 2.0 e lo convertirà felicemente in 2.
blubberdiblub

1
Se l'intenzione di OP (o chiunque leggerà questo in futuro) è di utilizzare il numero intero più vicino (e non il valore di arrotondamento) per qualsiasi motivo, allora sarebbe qualcosa da tenere a mente.
lokilindo

3
@lokilindo Ma questo non ha nulla a che fare con int(), ha solo a che fare con un uso improprio difloat , come 1.9999999999999999viene arrotondato 2.0 al momento della compilazione (mentre int()è chiamato in fase di esecuzione). Se utilizzi il tipo di dati corretto per la variabile, tutto funziona come previsto: int(decimal.Decimal('1.9999999999999999999999999999999999999999999999999999999'))1
Tino

6

Se non vuoi importare la matematica, puoi usare:

int(round(x))

Ecco un pezzo di documentazione:

>>> help(round)
Help on built-in function round in module __builtin__:

round(...)
    round(number[, ndigits]) -> floating point number

    Round a number to a given precision in decimal digits (default 0 digits).
    This always returns a floating point number.  Precision may be negative.

Grazie per la tua risposta. La prossima volta otterrai una migliore ricezione se scrivi codice corretto (chiudi parentesi) e fornisci della documentazione.
Geoff

2
roundè stato già discusso e rifiutato come risposta quando questa domanda è stata posta un anno fa. OP vuole math.floor.
Adam Smith,

3

Se lavori con numpy, puoi utilizzare la seguente soluzione che funziona anche con numeri negativi (funziona anche con gli array)

import numpy as np
def round_down(num):
    if num < 0:
        return -np.ceil(abs(num))
    else:
        return np.int32(num)
round_down = np.vectorize(round_down)

round_down([-1.1, -1.5, -1.6, 0, 1.1, 1.5, 1.6])
> array([-2., -2., -2.,  0.,  1.,  1.,  1.])

Penso che funzionerà anche se usi solo il mathmodulo invece del numpymodulo.


1

Non so se l'hai risolto, ma mi sono imbattuto in questa domanda. Se vuoi eliminare i punti decimali, puoi usare int (x) e eliminerà tutte le cifre decimali. Non c'è bisogno di usare round (x).


1

Basta fare round (x-0,5) questo restituirà sempre il valore intero arrotondato per difetto successivo del tuo Float. Puoi anche arrotondare facilmente per eccesso (x + 0,5)


-1

Potrebbe essere molto semplice, ma non potresti semplicemente arrotondarlo per poi meno 1? Per esempio:

number=1.5
round(number)-1
> 1

4
Questo dà la risposta sbagliata per interi interi. Ad esempio, 2,0 arrotondato per eccesso è 2 e se sottrai 1 ottieni il risultato errato 1.
Pascal Cuoq

@PascalCuoq Non capisco il tuo problema. Vuoi 1.0 come risultato? Perché OP voleva chiaramente arrotondare il numero al più vicino integer.
bad_keypoints

1
@bad_keypoints Non penso che l'OP voglia arrotondare 2.0 a 1.
Pascal Cuoq

@PascalCuoq scusa, ho appena guardato indietro alla risposta nel thread dei commenti di cui siamo.
bad_keypoints

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.