Lunghezza di un numero intero in Python


233

In Python, come trovi il numero di cifre in un numero intero?


1
Non capisco la tua domanda. Intendevi la dimensione di un numero intero? Vuoi trovare il numero di cifre? Si prega di precisare.
Batbrat,

Risposte:


317

Se vuoi la lunghezza di un numero intero come nel numero di cifre nell'intero, puoi sempre convertirlo in stringa come str(133)e trovare la sua lunghezza come len(str(123)).


18
Naturalmente, se stai cercando il numero di cifre, questo produrrà un risultato troppo grande per i numeri negativi, poiché conterà il segno negativo.
Chris Upchurch,

37
Ehi, questa è una soluzione lenta. Ho fatto un fattoriale di un numero casuale di 6 cifre e ho trovato la sua lunghezza. Questo metodo ha richiesto 95.891 secondi. E il Math.log10metodo ha impiegato solo 7.486343383789062e-05 secondi, circa 1501388 volte più veloce!
FadedCoder

1
Questo non è solo lento, ma consuma molta più memoria e può causare problemi in grandi numeri. usa Math.log10invece.
Peyman,

246

Senza conversione in stringa

import math
digits = int(math.log10(n))+1

Per gestire anche i numeri zero e negativi

import math
if n > 0:
    digits = int(math.log10(n))+1
elif n == 0:
    digits = 1
else:
    digits = int(math.log10(-n))+2 # +1 if you don't count the '-' 

Probabilmente vorresti metterlo in una funzione :)

Ecco alcuni parametri di riferimento. Il len(str())è già alle spalle per numeri pari abbastanza piccoli

timeit math.log10(2**8)
1000000 loops, best of 3: 746 ns per loop
timeit len(str(2**8))
1000000 loops, best of 3: 1.1 µs per loop

timeit math.log10(2**100)
1000000 loops, best of 3: 775 ns per loop
 timeit len(str(2**100))
100000 loops, best of 3: 3.2 µs per loop

timeit math.log10(2**10000)
1000000 loops, best of 3: 844 ns per loop
timeit len(str(2**10000))
100 loops, best of 3: 10.3 ms per loop

5
L'uso di log10 per questo è la soluzione di un matematico; usare len (str ()) è una soluzione per programmatori, più chiara e semplice.
Glenn Maynard,

68
@Glenn: spero sicuramente che tu non stia insinuando che questa sia una cattiva soluzione. La soluzione ingenua O (log10 n) del programmatore funziona bene nel codice di prototipazione ad-hoc, ma preferirei di gran lunga vedere i matematici un'elegante soluzione O (1) nel codice di produzione o in un'API pubblica. +1 per gnibbler.
Juliet,

5
@gnibbler: +1. Non ho mai capito che log10 può essere usato per trovare la grandezza di un numero. Vorrei poter votare più di una volta :).
Abbas,

14
Ciao! Vado qualcosa di strano, qualcuno può per favore di me spiegare perché int(math.log10(x)) +1per 99999999999999999999999999999999999999999999999999999999999999999999999( 71 nove ) restituisce 72 ? Pensavo di poter fare affidamento sul metodo log10 ma invece devo usare len (str (x)) :(
Marecky

6
Credo di conoscere la ragione dello strano comportamento, dovuto ad imprecisioni in virgola mobile, ad es. math.log10(999999999999999)è uguale a 14.999999999999998così int(math.log10(999999999999999))diventa 14. Ma allora math.log10(9999999999999999)è uguale a 16.0. Forse l'utilizzo roundè una soluzione a questo problema.
jamylak,

43

Tutte le soluzioni math.log10 ti daranno problemi.

math.log10 è veloce ma dà problemi quando il tuo numero è maggiore di 99999999999999997. Questo perché il float ha troppi 0,9, facendo arrotondare il risultato.

La soluzione consiste nell'utilizzare un metodo contatore contatore per i numeri al di sopra di tale soglia.

Per renderlo ancora più veloce, crea 10 ^ 16, 10 ^ 17 e così via e memorizza come variabili in un elenco. In questo modo, è come una ricerca da tavolo.

def getIntegerPlaces(theNumber):
    if theNumber <= 999999999999997:
        return int(math.log10(theNumber)) + 1
    else:
        counter = 15
        while theNumber >= 10**counter:
            counter += 1
        return counter

Grazie. Questo è un buon contro-esempio per math.log10. È interessante vedere come la rappresentazione binaria inverta i valori dando un risultato matematicamente errato.
WloHu,

allora len (str (num)) sarebbe meglio
Vighnesh Raut il

2
@Vighnesh Raut: E le magnitudini più lente
Chaitanya Bangera,

"È pericoloso fare affidamento su operazioni in virgola mobile che danno risultati esatti" - Mark Dickinson, un membro del core team di sviluppo di Python bugs.python.org/issue3724
Sreeragh AR

26

Python 2.* intrichiede 4 o 8 byte (32 o 64 bit), a seconda della build di Python. sys.maxint( 2**31-1per 32 bit, 2**63-1per 64 bit) indicherà quale delle due possibilità si ottiene.

In Python 3, ints (come longs in Python 2) può assumere dimensioni arbitrarie fino alla quantità di memoria disponibile; sys.getsizeofti dà un'indicazione buona per un dato valore, anche se non contano anche un certo overhead fisso:

>>> import sys
>>> sys.getsizeof(0)
12
>>> sys.getsizeof(2**99)
28

Se, come suggeriscono altre risposte, stai pensando a una rappresentazione in forma di stringa del valore intero, prendi semplicemente lenquella rappresentazione, sia nella base 10 o in altro modo!


Mi dispiace che questa risposta sia meno chiara. È informativo e al punto plausibile della domanda (se fosse solo più specifico su quale 'len' è desiderato). +1
mjv,

Sembra interessante ma non so come estrarre la lunghezza
Tjorriemorrie,

17

Sono passati diversi anni da quando questa domanda è stata posta, ma ho compilato un benchmark di diversi metodi per calcolare la lunghezza di un numero intero.

def libc_size(i): 
    return libc.snprintf(buf, 100, c_char_p(b'%i'), i) # equivalent to `return snprintf(buf, 100, "%i", i);`

def str_size(i):
    return len(str(i)) # Length of `i` as a string

def math_size(i):
    return 1 + math.floor(math.log10(i)) # 1 + floor of log10 of i

def exp_size(i):
    return int("{:.5e}".format(i).split("e")[1]) + 1 # e.g. `1e10` -> `10` + 1 -> 11

def mod_size(i):
    return len("%i" % i) # Uses string modulo instead of str(i)

def fmt_size(i):
    return len("{0}".format(i)) # Same as above but str.format

(la funzione libc richiede alcune impostazioni, che non ho incluso)

size_expè grazie a Brian Preslopsky, size_strè grazie a GeekTantra ed size_mathè grazie a John La Rooy

Ecco i risultati:

Time for libc size:      1.2204 μs
Time for string size:    309.41 ns
Time for math size:      329.54 ns
Time for exp size:       1.4902 μs
Time for mod size:       249.36 ns
Time for fmt size:       336.63 ns
In order of speed (fastest first):
+ mod_size (1.000000x)
+ str_size (1.240835x)
+ math_size (1.321577x)
+ fmt_size (1.350007x)
+ libc_size (4.894290x)
+ exp_size (5.976219x)

(Dichiarazione di non responsabilità: la funzione viene eseguita sugli ingressi da 1 a 1.000.000)

Ecco i risultati per sys.maxsize - 100000a sys.maxsize:

Time for libc size:      1.4686 μs
Time for string size:    395.76 ns
Time for math size:      485.94 ns
Time for exp size:       1.6826 μs
Time for mod size:       364.25 ns
Time for fmt size:       453.06 ns
In order of speed (fastest first):
+ mod_size (1.000000x)
+ str_size (1.086498x)
+ fmt_size (1.243817x)
+ math_size (1.334066x)
+ libc_size (4.031780x)
+ exp_size (4.619188x)

Come puoi vedere, mod_size( len("%i" % i)) è il più veloce, leggermente più veloce dell'uso str(i)e significativamente più veloce di altri.


Dovresti davvero includere il setup di libc, libc = ctyle.CDLL('libc.so.6', use_errno=True)(indovinando che sia così). E non funziona con numeri maggiori di sys.maxsizeperché i numeri in virgola mobile non possono essere "molto grandi". Quindi qualsiasi numero sopra quello, immagino che tu sia bloccato con uno dei metodi più lenti.
Torxed il

15

Lascia che il numero sia, nquindi il numero di cifre nè dato da:

math.floor(math.log10(n))+1

Nota che questo darà risposte corrette per + ve numeri interi <10e15. Oltre a ciò, i limiti di precisione del tipo di ritorno math.log10entrano in gioco e la risposta potrebbe essere diversa da 1. Vorrei semplicemente usare len(str(n))oltre; ciò richiede O(log(n))tempo che equivale a ripetere i poteri di 10.

Grazie a @SetiVolkylany per aver portato la mia attenzione a questa limitazione. È sorprendente come le soluzioni apparentemente corrette abbiano avvertenze nei dettagli di implementazione.


1
Non funziona se n al di fuori dell'intervallo [-999999999999997, 999999999999997]
PADYMKO

@SetiVolkylany, l'ho testato fino a 50 cifre per Python2.7 e 3.5. Basta fare un assert list(range(1,51)) == [math.floor(math.log10(n))+1 for n in (10**e for e in range(50))].
BiGYaN

2
provalo con Python2.7 o Python3.5 >>> math.floor(math.log10(999999999999997))+1 15.0 >>> math.floor(math.log10(999999999999998))+1 16.0. Guarda la mia risposta stackoverflow.com/a/42736085/6003870 .
PADYMKO,

12

Bene, senza convertire in stringa farei qualcosa del tipo:

def lenDigits(x): 
    """
    Assumes int(x)
    """

    x = abs(x)

    if x < 10:
        return 1

    return 1 + lenDigits(x / 10)

Minimalist recursion FTW


1
Raggiungerai il limite di ricorsione per grandi numeri.
nog642,

9

Contare il numero di cifre senza convertire un numero intero in una stringa:

x=123
x=abs(x)
i = 0
while x >= 10**i:
    i +=1
# i is the number of digits

Bello, evita completamente la conversione delle stringhe.
Patrick Mutuku,

8

Come accennato al caro utente @Calvintwr, la funzione math.log10ha un problema in un numero al di fuori di un intervallo [-99999999999999997, 999999999999997], in cui si verificano errori in virgola mobile. Ho avuto questo problema con JavaScript (Google V8 e NodeJS) e C (il compilatore GCC GNU), quindi una 'purely mathematically'soluzione è impossibile qui.


Sulla base di questa sintesi e della risposta il caro utente @Calvintwr

import math


def get_count_digits(number: int):
    """Return number of digits in a number."""

    if number == 0:
        return 1

    number = abs(number)

    if number <= 999999999999997:
        return math.floor(math.log10(number)) + 1

    count = 0
    while number:
        count += 1
        number //= 10
    return count

L'ho provato su numeri con lunghezza fino a 20 (incluso) e va bene. Deve essere sufficiente, perché il numero intero massimo lunghezza su un sistema a 64 bit è 19 ( len(str(sys.maxsize)) == 19).

assert get_count_digits(-99999999999999999999) == 20
assert get_count_digits(-10000000000000000000) == 20
assert get_count_digits(-9999999999999999999) == 19
assert get_count_digits(-1000000000000000000) == 19
assert get_count_digits(-999999999999999999) == 18
assert get_count_digits(-100000000000000000) == 18
assert get_count_digits(-99999999999999999) == 17
assert get_count_digits(-10000000000000000) == 17
assert get_count_digits(-9999999999999999) == 16
assert get_count_digits(-1000000000000000) == 16
assert get_count_digits(-999999999999999) == 15
assert get_count_digits(-100000000000000) == 15
assert get_count_digits(-99999999999999) == 14
assert get_count_digits(-10000000000000) == 14
assert get_count_digits(-9999999999999) == 13
assert get_count_digits(-1000000000000) == 13
assert get_count_digits(-999999999999) == 12
assert get_count_digits(-100000000000) == 12
assert get_count_digits(-99999999999) == 11
assert get_count_digits(-10000000000) == 11
assert get_count_digits(-9999999999) == 10
assert get_count_digits(-1000000000) == 10
assert get_count_digits(-999999999) == 9
assert get_count_digits(-100000000) == 9
assert get_count_digits(-99999999) == 8
assert get_count_digits(-10000000) == 8
assert get_count_digits(-9999999) == 7
assert get_count_digits(-1000000) == 7
assert get_count_digits(-999999) == 6
assert get_count_digits(-100000) == 6
assert get_count_digits(-99999) == 5
assert get_count_digits(-10000) == 5
assert get_count_digits(-9999) == 4
assert get_count_digits(-1000) == 4
assert get_count_digits(-999) == 3
assert get_count_digits(-100) == 3
assert get_count_digits(-99) == 2
assert get_count_digits(-10) == 2
assert get_count_digits(-9) == 1
assert get_count_digits(-1) == 1
assert get_count_digits(0) == 1
assert get_count_digits(1) == 1
assert get_count_digits(9) == 1
assert get_count_digits(10) == 2
assert get_count_digits(99) == 2
assert get_count_digits(100) == 3
assert get_count_digits(999) == 3
assert get_count_digits(1000) == 4
assert get_count_digits(9999) == 4
assert get_count_digits(10000) == 5
assert get_count_digits(99999) == 5
assert get_count_digits(100000) == 6
assert get_count_digits(999999) == 6
assert get_count_digits(1000000) == 7
assert get_count_digits(9999999) == 7
assert get_count_digits(10000000) == 8
assert get_count_digits(99999999) == 8
assert get_count_digits(100000000) == 9
assert get_count_digits(999999999) == 9
assert get_count_digits(1000000000) == 10
assert get_count_digits(9999999999) == 10
assert get_count_digits(10000000000) == 11
assert get_count_digits(99999999999) == 11
assert get_count_digits(100000000000) == 12
assert get_count_digits(999999999999) == 12
assert get_count_digits(1000000000000) == 13
assert get_count_digits(9999999999999) == 13
assert get_count_digits(10000000000000) == 14
assert get_count_digits(99999999999999) == 14
assert get_count_digits(100000000000000) == 15
assert get_count_digits(999999999999999) == 15
assert get_count_digits(1000000000000000) == 16
assert get_count_digits(9999999999999999) == 16
assert get_count_digits(10000000000000000) == 17
assert get_count_digits(99999999999999999) == 17
assert get_count_digits(100000000000000000) == 18
assert get_count_digits(999999999999999999) == 18
assert get_count_digits(1000000000000000000) == 19
assert get_count_digits(9999999999999999999) == 19
assert get_count_digits(10000000000000000000) == 20
assert get_count_digits(99999999999999999999) == 20

Tutti esempi di codici testati con Python 3.5


3

Per i posteri, senza dubbio la soluzione di gran lunga più lenta a questo problema:

def num_digits(num, number_of_calls=1):
    "Returns the number of digits of an integer num."
    if num == 0 or num == -1:
        return 1 if number_of_calls == 1 else 0
    else:
        return 1 + num_digits(num/10, number_of_calls+1)


1

Supponendo che tu stia chiedendo il numero più grande che puoi memorizzare in un numero intero, il valore dipende dall'implementazione. Ti suggerisco di non pensare in questo modo quando usi Python. In ogni caso, un valore abbastanza grande può essere memorizzato in un 'numero intero' di Python. Ricorda, Python usa la tipizzazione anatra!

Modifica: ho dato la mia risposta prima del chiarimento che il richiedente voleva il numero di cifre. Per questo, sono d'accordo con il metodo suggerito dalla risposta accettata. Nient'altro da aggiungere!


1
def length(i):
  return len(str(i))

1

Può essere fatto rapidamente per numeri interi usando:

len(str(abs(1234567890)))

Che ottiene la lunghezza della stringa del valore assoluto di "1234567890"

absrestituisce il numero SENZA eventuali negativi (solo la grandezza del numero), lo strlancia / converte in una stringa elen restituisce la lunghezza della stringa.

Se vuoi che funzioni per i float, puoi usare uno dei seguenti:

# Ignore all after decimal place
len(str(abs(0.1234567890)).split(".")[0])

# Ignore just the decimal place
len(str(abs(0.1234567890)))-1

Per riferimento futuro.


Penso che sarebbe più semplice troncare il numero di input stesso (ad es. Con un cast su int) piuttosto che troncare la sua rappresentazione in formato decimale: len(str(abs(int(0.1234567890))))restituisce 1.
David Foerster,

No, non funzionerebbe. Se trasformi 0.17 in un numero intero ottieni 0 e la lunghezza sarebbe diversa dalla lunghezza di 0.17
Frogboxe,

Nel primo caso, troncando tutto da e includendo il punto decimale fuori dalla rappresentazione della stringa, stai effettivamente calcolando la lunghezza della parte integrale del numero, che è anche quello che suggerisce il mio suggerimento. Per 0.17 entrambe le soluzioni restituiscono 1.
David Foerster,

0

Formatta in notazione scientifica e cancella l'esponente:

int("{:.5e}".format(1000000).split("e")[1]) + 1

Non conosco la velocità, ma è semplice.

Si noti che il numero di cifre significative dopo il decimale (il "5" in ".5e" può essere un problema se arrotonda la parte decimale della notazione scientifica ad un'altra cifra. L'ho impostata arbitrariamente grande, ma potrebbe riflettere il lunghezza del numero più grande che conosci.


0
def count_digit(number):
  if number >= 10:
    count = 2
  else:
    count = 1
  while number//10 > 9:
    count += 1
    number = number//10
  return count

Sebbene questo codice possa risolvere la domanda, inclusa una spiegazione di come e perché questo risolva il problema, aiuterebbe davvero a migliorare la qualità del tuo post e probabilmente comporterebbe più voti positivi. Ricorda che stai rispondendo alla domanda per i lettori in futuro, non solo per la persona che chiede ora. Si prega di modificare la risposta per aggiungere spiegazioni e dare un'indicazione di ciò si applicano le limitazioni e le assunzioni.
Adrian Mole,

0

Se devi chiedere a un utente di fornire un input e poi devi contare quanti numeri ci sono, puoi seguire questo:

count_number = input('Please enter a number\t')

print(len(count_number))

Nota: non prendere mai un int come input dell'utente.


Un caso piuttosto specifico che descrivi qui in quanto è effettivamente correlato alla lunghezza di una stringa. Inoltre, potrei inserire qualsiasi carattere non numerico e crederesti comunque che sia un numero.
Ben

0
def digits(n)
    count = 0
    if n == 0:
        return 1
    while (n >= 10**count):
        count += 1
        n += n%10
    return count
print(digits(25))   # Should print 2
print(digits(144))  # Should print 3
print(digits(1000)) # Should print 4
print(digits(0))    # Should print 1

0

Il mio codice per lo stesso è il seguente; ho usato il metodo log10:

from math import *

def digit_count (numero):

if number>1 and round(log10(number))>=log10(number) and number%10!=0 :
    return round(log10(number))
elif  number>1 and round(log10(number))<log10(number) and number%10!=0:
    return round(log10(number))+1
elif number%10==0 and number!=0:
    return int(log10(number)+1)
elif number==1 or number==0:
    return 1

Ho dovuto specificare in caso di 1 e 0 perché log10 (1) = 0 e log10 (0) = ND e quindi la condizione menzionata non è soddisfatta. Tuttavia, questo codice funziona solo per numeri interi.


0

Ecco una versione voluminosa ma veloce:

def nbdigit ( x ):
    if x >= 10000000000000000 : # 17 -
        return len( str( x ))
    if x < 100000000 : # 1 - 8
        if x < 10000 : # 1 - 4
            if x < 100             : return (x >= 10)+1 
            else                   : return (x >= 1000)+3
        else: # 5 - 8                                                 
            if x < 1000000         : return (x >= 100000)+5 
            else                   : return (x >= 10000000)+7
    else: # 9 - 16 
        if x < 1000000000000 : # 9 - 12
            if x < 10000000000     : return (x >= 1000000000)+9 
            else                   : return (x >= 100000000000)+11
        else: # 13 - 16
            if x < 100000000000000 : return (x >= 10000000000000)+13 
            else                   : return (x >= 1000000000000000)+15

Solo 5 confronti per numeri non troppo grandi. Sul mio computer è circa il 30% più veloce della math.log10versione e il 5% più veloce dellen( str()) quella. Ok ... non così attraente se non lo usi furiosamente.

Ed ecco la serie di numeri che ho usato per testare / misurare la mia funzione:

n = [ int( (i+1)**( 17/7. )) for i in xrange( 1000000 )] + [0,10**16-1,10**16,10**16+1]

NB: non gestisce numeri negativi, ma l'adattamento è facile ...


-13
>>> a=12345
>>> a.__str__().__len__()
5

6
Non chiamare direttamente metodi speciali. Questo è scritto len(str(a)).
Mike Graham,

8
@ ghostdog74 Solo perché c'è una presa elettrica, non significa che devi infilarci le dita.

3
quindi se sei così contrario, perché non mi dici cosa c'è che non va nell'usarlo?
ghostdog74

11
I metodi "Magic" __ sono disponibili per richiamare gli interni di Python, non per far chiamare direttamente il tuo codice. È il modello di Hollywood Framework: non chiamarci, ti chiameremo. Ma l'intento di questo framework è che questi sono metodi magici che gli built-in Python standard possono utilizzare, in modo che la tua classe possa personalizzare il comportamento del built-in. Se è un metodo che il tuo codice deve chiamare direttamente, assegna al metodo un nome non "__". Ciò separa chiaramente quei metodi che sono destinati al consumo del programmatore, rispetto a quelli forniti per il callback dagli built-in Python.
PaulMcG,

7
È una cattiva idea perché tutti gli altri nell'universo conosciuto usano str () e len (). Questo è diverso per il gusto di essere diverso, il che è intrinsecamente una cosa negativa - per non parlare del fatto che è brutto da morire. -1.
Glenn Maynard,
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.