En Python, comment trouvez-vous le nombre de chiffres dans un entier?
Si vous voulez que la longueur d'un entier corresponde au nombre de chiffres qu'il contient, vous pouvez toujours le convertir en chaîne telle que str(133)
et trouver sa longueur comme len(str(123))
.
Sans conversion en chaîne
import math
digits = int(math.log10(n))+1
Pour gérer également les nombres zéro et négatifs
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 '-'
Vous voudrez probablement mettre cela dans une fonction :)
Voici quelques repères. len(str())
est déjà en retard, même pour des nombres assez petits
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
math.log10 est rapide mais pose problème lorsque votre nombre est supérieur à 999999999999997. Cela est dû au fait que le nombre flottant contient trop de valeurs.
La solution consiste à utiliser une méthode de compteur de temps pour les nombres supérieurs à ce seuil.
Pour rendre cela encore plus rapide, créez 10 ^ 16, 10 ^ 17 etc. ainsi de suite et stockez-les sous forme de variables dans une liste. De cette façon, cela ressemble à une consultation de table.
def getIntegerPlaces(theNumber):
if theNumber <= 999999999999997:
return int(math.log10(theNumber)) + 1
else:
counter = 15
while theNumber >= 10**counter:
counter += 1
return counter
Python 2.*
int
s prend 4 ou 8 octets (32 ou 64 bits), en fonction de votre construction Python. sys.maxint
(2**31-1
pour les ints 32 bits, 2**63-1
pour les ints 64 bits) vous indiquera laquelle des deux possibilités est obtenue.
Dans Python 3, int
s (comme long
s dans Python 2) peut prendre des tailles arbitraires allant jusqu'à la quantité de mémoire disponible; sys.getsizeof
vous donne une bonne indication pour toute valeur donnée, bien qu'il compte compte également une surcharge fixe:
>>> import sys
>>> sys.getsizeof(0)
12
>>> sys.getsizeof(2**99)
28
Si, comme le suggèrent d'autres réponses, vous songez à une représentation sous forme de chaîne de la valeur entière, prenez simplement la variable len
de cette représentation, que ce soit en base 10 ou autrement!
Soit le nombre n
alors le nombre de chiffres dans n
est donné par:
math.floor(math.log10(n))+1
Notez que cela donnera des réponses correctes pour les nombres entiers supérieurs <10e15. Au-delà de cela, la limite de précision du type de retour de math.log10
commence et la réponse peut être décalée de 1. J'utiliserais simplement len(str(n))
au-delà; Cela nécessite O(log(n))
time, ce qui est identique à une itération sur des puissances de 10.
Merci à @SetiVolkylany d’avoir attiré mon attention sur cette limitation. Il est étonnant de voir à quel point les solutions apparemment correctes comportent des réserves quant aux détails de la mise en œuvre.
Eh bien, sans convertir en chaîne, je ferais quelque chose comme:
def lenDigits(x):
"""
Assumes int(x)
"""
x = abs(x)
if x < 10:
return 1
return 1 + lenDigits(x / 10)
Récursion minimaliste FTW
Comme mentionné le cher utilisateur @Calvintwr, la fonction math.log10
a un problème dans un nombre en dehors d'une plage [-999999999999997, 999999999999997], où nous obtenons des erreurs en virgule flottante. J'ai eu ce problème avec JavaScript (Google V8 et NodeJS) et C (le compilateur GNU GCC), de sorte qu'une solution 'purely mathematically'
est impossible ici.
Basé sur ceci Gist et la réponse le cher utilisateur @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
Je l'ai testé sur des nombres allant jusqu'à 20 (inclus) et tout va bien. Cela doit être suffisant, car le nombre entier max de longueur sur un système 64 bits est 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
Tous les exemples de codes testés avec Python 3.5
Pour la postérité, la solution la plus lente à ce problème est sans doute la plus lente:
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)
Cela fait plusieurs années que cette question a été posée, mais j'ai compilé un point de repère de plusieurs méthodes pour calculer la longueur d'un entier.
def size_libc(i):
return libc.snprintf(buf, 100, c_char_p(b'%i'), i) # equivalent to `return snprintf(buf, 100, "%i", i);`
def size_str(i):
return len(str(i)) # Length of `i` as a string
def size_math(i):
return 1 + math.floor(math.log10(i)) # 1 + floor of log10 of i
def size_exp(i):
return int("{:.5e}".format(i).split("e")[1]) + 1 # e.g. `1e10` -> `10` + 1 -> 11
def size_mod(i):
return len("%i" % i) # Uses string modulo instead of str(i)
def size_fmt(i):
return len("{0}".format(i)) # Same as above but str.format
(la fonction libc nécessite une configuration que je n'ai pas incluse)
size_exp
grâce à Brian Preslopsky, size_str
grâce à GeekTantra et size_math
grâce à John La Rooy
Voici les résultats:
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)
(Avertissement: la fonction est exécutée sur les entrées 1 à 1 000 000)
Voici les résultats pour sys.maxsize - 100000
à 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)
Comme vous pouvez le constater, mod_size
(len("%i" % i)
) est le plus rapide, légèrement plus rapide que l’utilisation de str(i)
et nettement plus rapide que d’autres.
from math import log10
digits = lambda n: ((n==0) and 1) or int(log10(abs(n)))+1
Cela peut être fait rapidement pour les entiers en utilisant:
len(str(abs(1234567890)))
Qui obtient la longueur de la chaîne de la valeur absolue de "1234567890"
abs
renvoie le nombre SANS aucun négatif (seulement la magnitude du nombre), str
le convertit/le convertit en chaîne et len
renvoie la longueur de chaîne de cette chaîne.
Si vous souhaitez que cela fonctionne pour les flotteurs, vous pouvez utiliser l’un des éléments suivants:
# Ignore all after decimal place
len(str(abs(0.1234567890)).split(".")[0])
# Ignore just the decimal place
len(str(abs(0.1234567890)))-1
Pour référence future.
def length(i):
return len(str(i))
En supposant que vous demandiez le plus grand nombre que vous puissiez stocker dans un entier, la valeur dépend de la mise en œuvre. Je suggère que vous ne pensiez pas de cette façon lorsque vous utilisez python. Dans tous les cas, une valeur assez grande peut être stockée dans un "entier" python. N'oubliez pas que Python utilise la frappe au canard!
Edit: J'ai donné ma réponse avant la clarification que le demandeur voulait le nombre de chiffres. Pour cela, je suis d’accord avec la méthode suggérée par la réponse acceptée. Rien de plus à ajouter!
Formater en notation scientifique et arracher l’exposant:
int("{:.5e}".format(1000000).split("e")[1]) + 1
Je ne connais pas la vitesse, mais c'est simple.
Veuillez noter le nombre de chiffres significatifs après la décimale (le "5" dans le ".5e" peut poser problème si la partie décimale de la notation scientifique est arrondie à un autre chiffre. longueur du plus grand nombre que vous connaissez.
Comptez le nombre de chiffres sans convertir un entier en chaîne:
x=123
x=abs(x)
i = 0
while x >= 10**i:
i +=1
# i is the number of digits