Wie finden Sie in Python die Anzahl der Stellen in einer Ganzzahl?
Wie finden Sie in Python die Anzahl der Stellen in einer Ganzzahl?
Antworten:
Wenn Sie die Länge einer Ganzzahl wie die Anzahl der Stellen in der Ganzzahl angeben möchten, können Sie sie jederzeit in eine Zeichenfolge wie konvertieren str(133)
und ihre Länge wie finden len(str(123))
.
Math.log10
Methode dauerte nur 7.486343383789062e-05 Sekunden, ungefähr 1501388 mal schneller!
Math.log10
stattdessen.
Ohne Konvertierung in einen String
import math
digits = int(math.log10(n))+1
Um auch mit Nullen und negativen Zahlen umzugehen
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 '-'
Du würdest das wahrscheinlich in eine Funktion einfügen wollen :)
Hier sind einige Benchmarks. Das len(str())
ist schon für ganz kleine Zahlen im Rückstand
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
für 99999999999999999999999999999999999999999999999999999999999999999999999
( 71 Neunen ) 72 zurückgegeben werden ? Ich dachte, ich könnte mich auf die log10-Methode verlassen, aber ich muss stattdessen len (str (x)) verwenden :(
math.log10(999999999999999)
ist gleich 14.999999999999998
so int(math.log10(999999999999999))
wird 14
. Aber dann math.log10(9999999999999999)
ist gleich 16.0
. Vielleicht ist die Verwendung round
eine Lösung für dieses Problem.
math.log10 ist schnell, gibt jedoch Probleme, wenn Ihre Zahl größer als 999999999999997 ist. Dies liegt daran, dass der Float zu viele 0,9 Sekunden hat, wodurch das Ergebnis aufgerundet wird.
Die Lösung besteht darin, eine while-Zählermethode für Zahlen über diesem Schwellenwert zu verwenden.
Um dies noch schneller zu machen, erstellen Sie 10 ^ 16, 10 ^ 17 usw. und speichern Sie sie als Variablen in einer Liste. Auf diese Weise ist es wie eine Tabellensuche.
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
. Es ist interessant zu sehen, wie die binäre Darstellung die Werte umdreht und ein mathematisch falsches Ergebnis liefert.
Pythons 2.*
int
benötigen je nach Python-Build entweder 4 oder 8 Byte (32 oder 64 Bit). sys.maxint
( 2**31-1
für 32-Bit-Ints, 2**63-1
für 64-Bit-Ints) zeigt Ihnen, welche der beiden Möglichkeiten sich ergibt.
In Python 3 kann int
s (wie long
s in Python 2) beliebige Größen bis zur Menge des verfügbaren Speichers annehmen. sys.getsizeof
gibt Ihnen einen guten Hinweis für einen bestimmten Wert, obwohl auch ein fester Overhead berücksichtigt wird :
>>> import sys
>>> sys.getsizeof(0)
12
>>> sys.getsizeof(2**99)
28
Wenn Sie, wie andere Antworten vermuten lassen, über eine Zeichenfolgendarstellung des ganzzahligen Werts nachdenken, nehmen Sie einfach die len
Darstellung dieser Darstellung, sei es in Basis 10 oder auf andere Weise!
Es ist einige Jahre her, seit diese Frage gestellt wurde, aber ich habe einen Benchmark mit mehreren Methoden zur Berechnung der Länge einer ganzen Zahl erstellt.
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
(Die libc-Funktion erfordert einige Einstellungen, die ich nicht aufgenommen habe.)
size_exp
ist dank Brian Preslopsky, size_str
ist dank GeekTantra und size_math
ist dank John La Rooy
Hier sind die Ergebnisse:
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)
(Haftungsausschluss: Die Funktion wird an den Eingängen 1 bis 1.000.000 ausgeführt.)
Hier sind die Ergebnisse für sys.maxsize - 100000
zu 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)
Wie Sie sehen können, ist mod_size
( len("%i" % i)
) am schnellsten, etwas schneller als die Verwendung str(i)
und deutlich schneller als andere.
libc = ctyle.CDLL('libc.so.6', use_errno=True)
( ich vermute, das ist es). Und es funktioniert nicht für Zahlen, die größer sind als sys.maxsize
weil Gleitkommazahlen nicht "sehr groß" sein können. Also jede Zahl darüber, ich denke, Sie stecken mit einer der langsameren Methoden fest.
Die Zahl sei n
dann die Anzahl der Ziffern in n
ist gegeben durch:
math.floor(math.log10(n))+1
Beachten Sie, dass dies korrekte Antworten für + ve ganze Zahlen <10e15 gibt. Darüber hinaus treten die Genauigkeitsgrenzen des Rückgabetyps ein math.log10
und die Antwort kann um 1 abweichen. Ich würde einfach len(str(n))
darüber hinaus verwenden. Dies erfordert O(log(n))
Zeit, die dem Iterieren über Potenzen von 10 entspricht.
Vielen Dank an @SetiVolkylany, dass Sie mich auf diese Einschränkung aufmerksam gemacht haben. Es ist erstaunlich, wie scheinbar korrekte Lösungen Einschränkungen bei den Implementierungsdetails aufweisen.
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
. Schauen Sie sich meine Antwort an stackoverflow.com/a/42736085/6003870 an .
Zählen Sie die Anzahl der Stellen, ohne die Ganzzahl in eine Zeichenfolge umzuwandeln:
x=123
x=abs(x)
i = 0
while x >= 10**i:
i +=1
# i is the number of digits
Wie der liebe Benutzer @Calvintwr erwähnt, hat die Funktion math.log10
ein Problem in einer Zahl außerhalb eines Bereichs [-999999999999997, 999999999999997], bei dem Gleitkommafehler auftreten. Ich hatte dieses Problem mit JavaScript (Google V8 und NodeJS) und C (GNU GCC-Compiler), daher 'purely mathematically'
ist hier keine Lösung möglich.
Basierend auf diesem Kern und der Antwort der liebe Benutzer @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
Ich habe es an Zahlen mit einer Länge von bis zu 20 (einschließlich) getestet. Dies muss ausreichen, da die maximale Ganzzahl auf einem 64-Bit-System 19 ( len(str(sys.maxsize)) == 19
) beträgt .
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
Alle Beispiele für Codes, die mit Python 3.5 getestet wurden
Für die Nachwelt zweifellos die mit Abstand langsamste Lösung für dieses Problem:
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
Angenommen, Sie fragen nach der größten Zahl, die Sie in einer Ganzzahl speichern können, ist der Wert implementierungsabhängig. Ich schlage vor, dass Sie bei der Verwendung von Python nicht so denken. In jedem Fall kann ein ziemlich großer Wert in einer Python-Ganzzahl gespeichert werden. Denken Sie daran, Python verwendet Enten-Typisierung!
Bearbeiten: Ich gab meine Antwort vor der Klarstellung, dass der Fragesteller die Anzahl der Ziffern wollte. Dafür stimme ich der in der akzeptierten Antwort vorgeschlagenen Methode zu. Nichts mehr hinzuzufügen!
def length(i):
return len(str(i))
Es kann für ganze Zahlen schnell durchgeführt werden, indem Folgendes verwendet wird:
len(str(abs(1234567890)))
Welches erhält die Länge der Zeichenfolge des absoluten Wertes von "1234567890"
abs
Gibt die Zahl OHNE Negative zurück (nur die Größe der Zahl), str
wandelt sie in eine Zeichenfolge um und konvertiert sie und len
gibt die Zeichenfolgenlänge dieser Zeichenfolge zurück.
Wenn Sie möchten, dass es für Floats funktioniert, können Sie eine der folgenden Methoden verwenden:
# Ignore all after decimal place
len(str(abs(0.1234567890)).split(".")[0])
# Ignore just the decimal place
len(str(abs(0.1234567890)))-1
Zum späteren Nachschlagen.
int
), als ihre dezimale Zeichenfolgendarstellung abzuschneiden: len(str(abs(int(0.1234567890))))
gibt 1 zurück.
Formatieren Sie in wissenschaftlicher Notation und reißen Sie den Exponenten ab:
int("{:.5e}".format(1000000).split("e")[1]) + 1
Ich weiß nichts über Geschwindigkeit, aber es ist einfach.
Bitte beachten Sie die Anzahl der signifikanten Stellen nach der Dezimalstelle (die "5" in der ".5e" kann ein Problem sein, wenn sie den Dezimalteil der wissenschaftlichen Notation auf eine andere Ziffer aufrundet. Ich habe sie beliebig groß eingestellt, könnte aber die widerspiegeln Länge der größten Zahl, die Sie kennen.
def count_digit(number):
if number >= 10:
count = 2
else:
count = 1
while number//10 > 9:
count += 1
number = number//10
return count
Wenn Sie einen Benutzer zur Eingabe auffordern müssen und dann zählen müssen, wie viele Zahlen vorhanden sind, können Sie Folgendes tun:
count_number = input('Please enter a number\t')
print(len(count_number))
Hinweis: Nehmen Sie niemals ein int als Benutzereingabe.
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
Mein Code für das gleiche ist wie folgt: Ich habe die log10-Methode verwendet:
from math import *
def digit_count (number):
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
Ich musste im Fall von 1 und 0 angeben, weil log10 (1) = 0 und log10 (0) = ND und daher die erwähnte Bedingung nicht erfüllt ist. Dieser Code funktioniert jedoch nur für ganze Zahlen.
Hier ist eine sperrige, aber schnelle Version:
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
Nur 5 Vergleiche für nicht zu große Zahlen. Auf meinem Computer ist es ungefähr 30% schneller als die math.log10
Version und 5% schneller als die len( str())
. Ok ... nein, so attraktiv, wenn du es nicht wütend benutzt.
Und hier sind die Zahlen, mit denen ich meine Funktion getestet / gemessen habe:
n = [ int( (i+1)**( 17/7. )) for i in xrange( 1000000 )] + [0,10**16-1,10**16,10**16+1]
NB: Es werden keine negativen Zahlen verwaltet, aber die Anpassung ist einfach ...
>>> a=12345
>>> a.__str__().__len__()
5
len(str(a))
.