wake-up-neo.com

Länge einer Ganzzahl in Python

Wie finden Sie in Python die Anzahl der Ziffern in einer Ganzzahl?

169
Strigoides

Wenn Sie die Länge einer Ganzzahl als Anzahl der Ziffern in der Ganzzahl angeben möchten, können Sie sie immer in einen String wie str(133) konvertieren und ihre Länge wie len(str(123)) finden. 

220
GeekTantra

Ohne Konvertierung in String

import math
digits = int(math.log10(n))+1

Um auch Null und negative Zahlen zu behandeln

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 '-' 

Sie möchten das wahrscheinlich in eine Funktion setzen :)

Hier sind einige Benchmarks. Die len(str()) ist bereits für recht kleine Zahlen hinterher 

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
181
John La Rooy

Alle math.log10-Lösungen geben Ihnen Probleme.

math.log10 ist schnell, führt jedoch zu Problemen, wenn Ihre Zahl größer als 999999999999997 ist. Dies liegt daran, dass der Float-Wert zu viele .9-Werte hat und das Ergebnis aufrundet.

Die Lösung ist die Verwendung einer while-Counter-Methode für Zahlen oberhalb dieser Schwelle.

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
26
Calvintwr

Python 2.*ints benötigt 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) gibt an, welche der beiden Möglichkeiten verfügbar ist.

In Python 3 können ints (wie longs in Python 2) beliebige Größen bis zur Größe des verfügbaren Speichers aufnehmen. sys.getsizeof gibt Ihnen eine gute Anzeige für jeden gegebenen Wert, obwohl er tut auch einen festen Overhead zählt:

>>> import sys
>>> sys.getsizeof(0)
12
>>> sys.getsizeof(2**99)
28

Wenn Sie, wie andere Antworten vermuten lassen, über eine String-Darstellung des ganzzahligen Werts nachdenken, nehmen Sie einfach die len dieser Darstellung, sei es in der Basis 10 oder anders!

20
Alex Martelli

Sei die Zahl n, dann ist die Anzahl der Ziffern in n gegeben durch:

math.floor(math.log10(n))+1

Beachten Sie, dass dies für + ve Ganzzahlen <10e15 korrekte Antworten gibt. Darüber hinaus setzen die Genauigkeitsgrenzen des Rückgabetyps von math.log10 ein 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 der Iteration von 10er-Werten entspricht.

Vielen Dank an @SetiVolkylany, dass ich meine Aufmerksamkeit auf diese Einschränkung gelenkt habe. Es ist erstaunlich, wie scheinbar korrekte Lösungen Vorbehalte bei den Implementierungsdetails haben.

13
BiGYaN

Nun, ohne in String umzuwandeln, würde ich so etwas tun:

def lenDigits(x): 
    """
    Assumes int(x)
    """

    x = abs(x)

    if x < 10:
        return 1

    return 1 + lenDigits(x / 10)

Minimalistische Rekursion FTW

11
odradek

Wie der liebe Benutzer @Calvintwr erwähnt hat, hat die Funktion math.log10 ein Problem außerhalb des Bereichs [-9999999999997, 999999999999997], bei dem Fließkommafehler auftreten. Ich hatte dieses Problem mit dem JavaScript (dem Google V8 und dem NodeJS) und dem C (dem GNU GCC-Compiler), daher ist hier keine 'purely mathematically'-Lösung möglich.


Basierend auf dieser Gist und der Antwort dem lieben 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 (inklusive) getestet. Es muss ausreichend sein, da die maximale Anzahl von Ganzzahlen auf einem 64-Bit-System 19 ist (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

Alle Beispiele für Codes, die mit Python 3.5 getestet wurden

5
Seti Volkylany

Für die Nachwelt zweifellos die 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)

Diese Frage wurde vor einigen Jahren gestellt, aber ich habe einen Benchmark aus mehreren Methoden zusammengestellt, um die Länge einer Ganzzahl zu berechnen. 

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

(Die libc-Funktion erfordert einige Einstellungen, die ich nicht mitgeliefert habe)

size_exp verdankt sich Brian Preslopsky, size_str verdankt sich GeekTantra und size_math verdanken 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 bis 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, ist mod_size (len("%i" % i)) am schnellsten, etwas schneller als str(i) und deutlich schneller als andere.

3
NoOneIsHere
from math import log10
digits = lambda n: ((n==0) and 1) or int(log10(abs(n)))+1

Es kann schnell für ganze Zahlen verwendet werden, indem Folgendes verwendet wird:

len(str(abs(1234567890)))

Welches ist die Länge der Zeichenfolge des absoluten Wertes von "1234567890"

abs gibt die Zahl OHNE Negative zurück (nur die Größe der Zahl), wandelt str sie in einen String um und len gibt die Stringlänge des Strings zurück.

Wenn es für Floats funktionieren soll, können Sie eine der folgenden Möglichkeiten verwenden:

# Ignore all after decimal place
len(str(abs(0.1234567890)).split(".")[0])

# Ignore just the decimal place
len(str(abs(0.1234567890)))-1

Für zukünftige Referenz.

1
Frogboxe
def length(i):
  return len(str(i))
1
user467871

Angenommen, Sie fragen nach der größten Anzahl, die Sie in einer Ganzzahl speichern können, ist der Wert von der Implementierung abhängig. Ich denke, dass Sie nicht so denken, wenn Sie Python verwenden. In jedem Fall kann ein ziemlich großer Wert in einer Python-Ganzzahl gespeichert werden. Denken Sie daran, dass Python die Eingabe von Enten verwendet!

Edit: Ich gab meine Antwort vor der Klarstellung, dass der Fragesteller die Anzahl der Ziffern haben wollte. Dafür stimme ich der von der akzeptierten Antwort vorgeschlagenen Methode zu. Nichts mehr hinzuzufügen!

1
batbrat

Formatieren Sie in wissenschaftlicher Notation und reißen Sie den Exponenten ab:

int("{:.5e}".format(1000000).split("e")[1]) + 1

Ich weiß nicht über Geschwindigkeit, aber es ist einfach. 

Bitte beachten Sie die Anzahl der signifikanten Stellen nach dem Dezimalzeichen (die "5" in der ".5e") kann ein Problem sein, wenn der Dezimalteil der wissenschaftlichen Schreibweise auf eine andere Zahl gerundet wird Länge der größten Zahl, die Sie kennen. 

0

Zählen Sie die Anzahl der Ziffern, ohne eine Ganzzahl in einen String zu konvertieren:

x=123
x=abs(x)
i = 0
while x >= 10**i:
    i +=1
# i is the number of digits
0
datanew