En Python, comment trouvez-vous le nombre de chiffres dans un entier?
En Python, comment trouvez-vous le nombre de chiffres dans un entier?
Réponses:
Si vous voulez la longueur d'un entier comme dans le nombre de chiffres de l'entier, vous pouvez toujours le convertir en chaîne comme str(133)
et trouver sa longueur comme len(str(123))
.
Math.log10
méthode n'a pris que 7.486343383789062e-05 secondes, environ 1501388 fois plus rapide!
Math.log10
place.
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 voudriez probablement mettre cela dans une fonction :)
Voici quelques repères. Le len(str())
est déjà en retard, même pour de très petits nombres
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
pour 99999999999999999999999999999999999999999999999999999999999999999999999
( 71 neuf ) renvoie 72 ? Je pensais que je pouvais compter sur la méthode log10 mais je dois utiliser len (str (x)) à la place :(
math.log10(999999999999999)
est égal à devient 14.999999999999998
ainsi . Mais alors est égal à . Peut-être que l'utilisation est une solution à ce problème. int(math.log10(999999999999999))
14
math.log10(9999999999999999)
16.0
round
math.log10 est rapide mais pose problème lorsque votre nombre est supérieur à 999999999999997. Cela est dû au fait que le flotteur a trop de 0,9, provoquant l'arrondi du résultat.
La solution consiste à utiliser une méthode de compteur while pour les nombres supérieurs à ce seuil.
Pour rendre cela encore plus rapide, créez 10 ^ 16, 10 ^ 17 ainsi de suite et stockez-les sous forme de variables dans une liste. De cette façon, c'est comme une recherche 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
math.log10
. Il est intéressant de voir comment la représentation binaire retourne les valeurs donnant un résultat mathématiquement incorrect.
Les Python 2.*
int
prennent 4 ou 8 octets (32 ou 64 bits), selon votre build Python. sys.maxint
( 2**31-1
pour les 32 bits, 2**63-1
pour les 64 bits) vous dira laquelle des deux possibilités obtient.
En Python 3, int
s (comme long
s en Python 2) peut prendre des tailles arbitraires jusqu'à la quantité de mémoire disponible; sys.getsizeof
vous donne une bonne indication pour une valeur donnée, même si elle ne compte aussi des frais généraux fixes:
>>> import sys
>>> sys.getsizeof(0)
12
>>> sys.getsizeof(2**99)
28
Si, comme d'autres réponses le suggèrent, vous pensez à une représentation sous forme de chaîne de la valeur entière, alors prenez simplement la len
représentation de cette représentation, que ce soit en base 10 ou autrement!
Cela fait plusieurs années que cette question a été posée, mais j'ai compilé une référence de plusieurs méthodes pour calculer la longueur d'un entier.
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 fonction libc nécessite une configuration, que je n'ai pas incluse)
size_exp
merci à Brian Preslopsky, size_str
merci à GeekTantra et size_math
merci à 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 voir, mod_size
( len("%i" % i)
) est le plus rapide, légèrement plus rapide que l'utilisation str(i)
et nettement plus rapide que les autres.
libc = ctyle.CDLL('libc.so.6', use_errno=True)
(devinant que c'est tout). Et cela ne fonctionne pas pour les nombres supérieurs à sys.maxsize
parce que les nombres à virgule flottante ne peuvent pas être "très grands". Donc, tout nombre supérieur à cela, je suppose que vous êtes coincé avec l'une des méthodes les plus lentes.
Soit le nombre n
alors le nombre de chiffres n
est donné par:
math.floor(math.log10(n))+1
Notez que cela donnera des réponses correctes pour les entiers + ve <10e15. Au-delà de cela, les limites de précision du type de retour de math.log10
coups de pied et la réponse peuvent être désactivées par 1. Je voudrais simplement utiliser len(str(n))
au-delà de cela; cela nécessite du O(log(n))
temps qui équivaut à itérer sur des puissances de 10.
Merci à @SetiVolkylany d'avoir apporté mon attention à cette limitation. Il est étonnant de constater à quel point les solutions apparemment correctes comportent des avertissements dans les détails de mise en œuvre.
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
. Regardez ma réponse stackoverflow.com/a/42736085/6003870 .
Comptez le nombre de chiffres sans convertir un entier en une chaîne:
x=123
x=abs(x)
i = 0
while x >= 10**i:
i +=1
# i is the number of digits
Comme mentionné le cher utilisateur @Calvintwr, la fonction math.log10
a un problème dans un certain nombre en dehors d'une plage [-999999999999997, 999999999999997], où nous obtenons des erreurs en virgule flottante. J'ai eu ce problème avec le JavaScript (le Google V8 et le NodeJS) et le C (le compilateur GNU GCC), donc une 'purely mathematically'
solution est impossible ici.
Sur la base de cet essentiel et de 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 numéros jusqu'à 20 (inclus) et très bien. Cela doit être suffisant, car le nombre entier de longueur maximale 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é, sans doute de loin la solution la plus lente à ce problème:
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
En supposant que vous demandez le plus grand nombre que vous pouvez stocker dans un entier, la valeur dépend de l'implémentation. Je suggère que vous ne pensiez pas de cette façon lorsque vous utilisez python. Dans tous les cas, une valeur assez importante peut être stockée dans un «entier» python. Rappelez-vous, Python utilise la frappe de 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!
def length(i):
return len(str(i))
Cela peut être fait pour les entiers rapidement 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 (uniquement l'amplitude du nombre), le str
convertit / convertit en chaîne et len
renvoie la longueur de chaîne de cette chaîne.
Si vous souhaitez qu'il fonctionne pour les flottants, vous pouvez utiliser l'une des méthodes suivantes:
# 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.
int
) que de tronquer sa représentation de chaîne décimale: len(str(abs(int(0.1234567890))))
renvoie 1.
Format 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 être un problème s'il arrondit la partie décimale de la notation scientifique à un autre chiffre. Je l'ai défini arbitrairement grand, mais pourrait refléter le longueur du plus grand nombre que vous connaissez.
def count_digit(number):
if number >= 10:
count = 2
else:
count = 1
while number//10 > 9:
count += 1
number = number//10
return count
Si vous devez demander à un utilisateur de donner une entrée et que vous devez ensuite compter le nombre de numéros, vous pouvez suivre ceci:
count_number = input('Please enter a number\t')
print(len(count_number))
Remarque: Ne prenez jamais un int comme entrée utilisateur.
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
Mon code pour le même est le suivant; j'ai utilisé la méthode log10:
from math import *
def digit_count (nombre):
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
J'ai dû spécifier en cas de 1 et 0 car log10 (1) = 0 et log10 (0) = ND et donc la condition mentionnée n'est pas remplie. Cependant, ce code ne fonctionne que pour les nombres entiers.
Voici une version volumineuse mais rapide:
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
Seulement 5 comparaisons pour des nombres pas trop grands. Sur mon ordinateur, elle est environ 30% plus rapide que la math.log10
version et 5% plus rapide que len( str())
celle. Ok ... pas si attrayant si vous ne l'utilisez pas furieusement.
Et voici l'ensemble de nombres que j'ai utilisé pour tester / mesurer ma fonction:
n = [ int( (i+1)**( 17/7. )) for i in xrange( 1000000 )] + [0,10**16-1,10**16,10**16+1]
NB: il ne gère pas les nombres négatifs, mais l'adaptation est facile ...
>>> a=12345
>>> a.__str__().__len__()
5
len(str(a))
.