Je ne comprends pas ta question. Voulez-vous dire la taille d'un entier? Voulez-vous trouver le nombre de chiffres? Précisez s'il vous plaît.
batbrat
Réponses:
317
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)).
Bien sûr, si vous recherchez le nombre de chiffres, cela produira un résultat trop grand pour les nombres négatifs, car il comptera le signe négatif.
Chris Upchurch
37
Hé, c'est une solution lente. J'ai fait une factorielle d'un nombre aléatoire à 6 chiffres et trouvé sa longueur. Cette méthode a pris 95,891 secondes. Et la Math.log10méthode n'a pris que 7.486343383789062e-05 secondes, environ 1501388 fois plus rapide!
FadedCoder
1
Ce n'est pas seulement lent, mais consomme beaucoup plus de mémoire et peut causer des problèmes en grand nombre. utiliser à la Math.log10place.
Peyman
246
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))+1elif n ==0:
digits =1else:
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
Utiliser log10 pour cela est une solution de mathématicien; l'utilisation de len (str ()) est une solution de programmeur, plus claire et plus simple.
Glenn Maynard
68
@Glenn: J'espère certainement que vous n'impliquez pas que c'est une mauvaise solution. La solution naïve O (log10 n) du programmeur fonctionne bien dans le code de prototypage ad hoc - mais je préfère de loin voir la solution O (1) élégante des mathématiciens dans le code de production ou une API publique. +1 pour grignoteur.
Juliet
5
@ grignoteur: +1. Jamais réalisé que log10 peut être utilisé pour trouver la grandeur d'un nombre. J'aimerais pouvoir voter plus d'une fois :).
Abbas
14
Salut! Je fais quelque chose d'étrange, est-ce que n'importe qui d'entre vous peut m'expliquer pourquoi int(math.log10(x)) +1pour 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 :(
Marecky
6
Je crois que je connais la raison de ce comportement étrange, il est dû à des inexactitudes en virgule flottante, par exemple. math.log10(999999999999999)est égal à devient 14.999999999999998ainsi . Mais alors est égal à . Peut-être que l'utilisation est une solution à ce problème. int(math.log10(999999999999999))14math.log10(9999999999999999)16.0round
jamylak
43
Toutes les solutions de math.log10 vous poseront des problèmes.
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.
Je vous remercie. C'est un bon contre-exemple pour math.log10. Il est intéressant de voir comment la représentation binaire retourne les valeurs donnant un résultat mathématiquement incorrect.
WloHu
alors len (str (num)) serait mieux
Vighnesh Raut
2
@Vighnesh Raut: Et les amplitudes plus lentes
Chaitanya Bangera
"Il est dangereux de s'appuyer sur des opérations en virgule flottante pour obtenir des résultats exacts" - Mark Dickinson, membre de l'équipe de développement Python principale bugs.python.org/issue3724
Sreeragh AR
26
Les Python 2.*intprennent 4 ou 8 octets (32 ou 64 bits), selon votre build Python. sys.maxint( 2**31-1pour les 32 bits, 2**63-1pour les 64 bits) vous dira laquelle des deux possibilités obtient.
En Python 3, ints (comme longs en Python 2) peut prendre des tailles arbitraires jusqu'à la quantité de mémoire disponible; sys.getsizeofvous donne une bonne indication pour une valeur donnée, même si elle ne compte aussi des frais généraux fixes:
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 lenreprésentation de cette représentation, que ce soit en base 10 ou autrement!
Désolé, cette réponse a été réduite. Elle est informative et va dans le sens plausible de la question (si elle n'était que plus précise sur le «len» souhaité). +1
mjv
Cela semble intéressant mais
je
17
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 stringdef math_size(i):return1+ math.floor(math.log10(i))# 1 + floor of log10 of idef exp_size(i):return int("{:.5e}".format(i).split("e")[1])+1# e.g. `1e10` -> `10` + 1 -> 11def 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_expmerci à Brian Preslopsky, size_strmerci à GeekTantra et size_mathmerci à John La Rooy
Voici les résultats:
Timefor libc size:1.2204μs
Timefor string size:309.41 ns
Timefor math size:329.54 ns
Timefor exp size:1.4902μs
Timefor mod size:249.36 ns
Timefor 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:
Timefor libc size:1.4686μs
Timefor string size:395.76 ns
Timefor math size:485.94 ns
Timefor exp size:1.6826μs
Timefor mod size:364.25 ns
Timefor 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.
Vous devriez vraiment inclure la configuration de la libc, 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.maxsizeparce 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.
Torxed
15
Soit le nombre nalors le nombre de chiffres nest 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.log10coups 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.
Cela ne fonctionne pas si n en dehors de la plage [-999999999999997, 999999999999997]
PADYMKO
@SetiVolkylany, je l'ai testé jusqu'à 50 chiffres pour python2.7 et 3.5. Faites juste un assert list(range(1,51)) == [math.floor(math.log10(n))+1 for n in (10**e for e in range(50))].
BiGYaN
2
essayez-le avec Python2.7 ou Python3.5 >>> 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 .
PADYMKO
12
Eh bien, sans convertir en chaîne, je ferais quelque chose comme:
def lenDigits(x):"""
Assumes int(x)
"""
x = abs(x)if x <10:return1return1+ lenDigits(x /10)
Nice on évite complètement la conversion de chaîne.
Patrick Mutuku
8
Comme mentionné le cher utilisateur @Calvintwr, la fonction math.log10a 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:return1
number = abs(number)if number <=999999999999997:return math.floor(math.log10(number))+1
count =0while number:
count +=1
number //=10return 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).
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 ==0or num ==-1:return1if number_of_calls ==1else0else:return1+ num_digits(num/10, number_of_calls+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!
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"
absrenvoie le nombre SANS aucun négatif (uniquement l'amplitude du nombre), le strconvertit / convertit en chaîne et lenrenvoie 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
Je pense qu'il serait plus simple de tronquer le numéro d'entrée lui-même (par exemple avec un transtypage en int) que de tronquer sa représentation de chaîne décimale: len(str(abs(int(0.1234567890))))renvoie 1.
David Foerster
Non, ça ne marcherait pas. Si vous transformez 0,17 en entier, vous obtenez 0 et la longueur de celui-ci serait différente de la longueur de 0,17
Frogboxe
Dans le premier cas, en tronquant tout à partir de la représentation sous forme de chaîne et en l'incluant, vous calculez effectivement la longueur de la partie intégrante du nombre, ce que fait également ma suggestion. Pour 0,17, les deux solutions renvoient 1.
David Foerster
0
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.
Bien que ce code puisse résoudre la question, y compris une explication de comment et pourquoi cela résout le problème aiderait vraiment à améliorer la qualité de votre message, et entraînerait probablement plus de votes positifs. N'oubliez pas que vous répondrez à la question aux lecteurs à l'avenir, pas seulement à la personne qui pose la question maintenant. Veuillez modifier votre réponse pour ajouter des explications et donner une indication des limitations et hypothèses applicables.
Adrian Mole
0
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.
Un cas assez spécifique que vous décrivez ici car il est en fait lié à la longueur d'une chaîne. De plus, je pourrais entrer n'importe quel caractère non numérique et vous croiriez toujours qu'il s'agit d'un nombre.
Ben
0
def digits(n)
count =0if n ==0:return1while(n >=10**count):
count +=1
n += n%10return count
print(digits(25))# Should print 2print(digits(144))# Should print 3print(digits(1000))# Should print 4print(digits(0))# Should print 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.
def nbdigit ( x ):if x >=10000000000000000:# 17 -return len( str( x ))if x <100000000:# 1 - 8if x <10000:# 1 - 4if x <100:return(x >=10)+1else:return(x >=1000)+3else:# 5 - 8 if x <1000000:return(x >=100000)+5else:return(x >=10000000)+7else:# 9 - 16 if x <1000000000000:# 9 - 12if x <10000000000:return(x >=1000000000)+9else:return(x >=100000000000)+11else:# 13 - 16if x <100000000000000:return(x >=10000000000000)+13else: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.log10version 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 ...
N'appelez pas directement des méthodes spéciales. C'est écrit len(str(a)).
Mike Graham
8
@ ghostdog74 Ce n'est pas parce qu'il y a une prise électrique que vous devez y mettre les doigts.
3
donc si vous êtes contre, pourquoi ne me dites-vous pas ce qui ne va pas avec ça?
ghostdog74
11
Les méthodes "magiques" __ sont là pour que les internes de Python puissent rappeler, pas pour que votre code appelle directement. C'est le modèle Hollywood Framework: ne nous appelez pas, nous vous appellerons. Mais l'intention de ce cadre est que ce sont des méthodes magiques pour les intégrées Python standard à utiliser, afin que votre classe puisse personnaliser le comportement de l'intégration. Si c'est une méthode que votre code appelle directement, donnez à la méthode un nom différent de "__". Cela sépare clairement les méthodes qui sont destinées à la consommation du programmeur, par rapport à celles qui sont fournies pour le rappel des fonctionnalités intégrées de Python.
PaulMcG
7
C'est une mauvaise idée car tout le monde dans l'univers connu utilise str () et len (). C'est différent pour le plaisir d'être différent, ce qui est intrinsèquement une mauvaise chose - sans compter que c'est tout simplement laid comme l'enfer. -1.
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 commelen(str(123))
.la source
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
Pour gérer également les nombres zéro et négatifs
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 nombresla source
int(math.log10(x)) +1
pour99999999999999999999999999999999999999999999999999999999999999999999999
( 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 à devient14.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
Toutes les solutions de math.log10 vous poseront des problèmes.
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.
la source
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 (commelong
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: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!la source
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.
(la fonction libc nécessite une configuration, que je n'ai pas incluse)
size_exp
merci à Brian Preslopsky,size_str
merci à GeekTantra etsize_math
merci à John La RooyVoici les résultats:
(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
:Comme vous pouvez le voir,
mod_size
(len("%i" % i)
) est le plus rapide, légèrement plus rapide que l'utilisationstr(i)
et nettement plus rapide que les autres.la source
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 chiffresn
est donné par: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 utiliserlen(str(n))
au-delà de cela; cela nécessite duO(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.
la source
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 .Eh bien, sans convertir en chaîne, je ferais quelque chose comme:
FTW récursivité minimaliste
la source
Comptez le nombre de chiffres sans convertir un entier en une chaîne:
la source
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
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
).Tous les exemples de codes testés avec Python 3.5
la source
Pour la postérité, sans doute de loin la solution la plus lente à ce problème:
la source
la source
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!
la source
la source
Cela peut être fait pour les entiers rapidement en utilisant:
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), lestr
convertit / convertit en chaîne etlen
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:
Pour référence future.
la source
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:
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.
la source
la source
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:
Remarque: Ne prenez jamais un int comme entrée utilisateur.
la source
la source
Mon code pour le même est le suivant; j'ai utilisé la méthode log10:
def digit_count (nombre):
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.
la source
Voici une version volumineuse mais rapide:
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 quelen( 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:
NB: il ne gère pas les nombres négatifs, mais l'adaptation est facile ...
la source
la source
len(str(a))
.