In Python, come trovi il numero di cifre in un numero intero?
In Python, come trovi il numero di cifre in un numero intero?
Risposte:
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))
.
Math.log10
metodo ha impiegato solo 7.486343383789062e-05 secondi, circa 1501388 volte più veloce!
Math.log10
invece.
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
int(math.log10(x)) +1
per 99999999999999999999999999999999999999999999999999999999999999999999999
( 71 nove ) restituisce 72 ? Pensavo di poter fare affidamento sul metodo log10 ma invece devo usare len (str (x)) :(
math.log10(999999999999999)
è uguale a 14.999999999999998
così int(math.log10(999999999999999))
diventa 14
. Ma allora math.log10(9999999999999999)
è uguale a 16.0
. Forse l'utilizzo round
è una soluzione a questo problema.
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
math.log10
. È interessante vedere come la rappresentazione binaria inverta i valori dando un risultato matematicamente errato.
Python 2.*
int
richiede 4 o 8 byte (32 o 64 bit), a seconda della build di Python. sys.maxint
( 2**31-1
per 32 bit, 2**63-1
per 64 bit) indicherà quale delle due possibilità si ottiene.
In Python 3, int
s (come long
s in Python 2) può assumere dimensioni arbitrarie fino alla quantità di memoria disponibile; sys.getsizeof
ti 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 len
quella rappresentazione, sia nella base 10 o in altro modo!
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 - 100000
a 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.
libc = ctyle.CDLL('libc.so.6', use_errno=True)
(indovinando che sia così). E non funziona con numeri maggiori di sys.maxsize
perché 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.
Lascia che il numero sia, n
quindi 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.log10
entrano 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.
assert list(range(1,51)) == [math.floor(math.log10(n))+1 for n in (10**e for e in range(50))]
.
>>> 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 .
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
Come accennato al caro utente @Calvintwr, la funzione math.log10
ha 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
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)
from math import log10
digits = lambda n: ((n==0) and 1) or int(log10(abs(n)))+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!
def length(i):
return len(str(i))
Può essere fatto rapidamente per numeri interi usando:
len(str(abs(1234567890)))
Che ottiene la lunghezza della stringa del valore assoluto di "1234567890"
abs
restituisce il numero SENZA eventuali negativi (solo la grandezza del numero), lo str
lancia / 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.
int
) piuttosto che troncare la sua rappresentazione in formato decimale: len(str(abs(int(0.1234567890))))
restituisce 1.
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.
def count_digit(number):
if number >= 10:
count = 2
else:
count = 1
while number//10 > 9:
count += 1
number = number//10
return count
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.
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
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.
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.log10
versione 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 ...
>>> a=12345
>>> a.__str__().__len__()
5
len(str(a))
.