W Pythonie, jak znaleźć liczbę cyfr w liczbie całkowitej?
W Pythonie, jak znaleźć liczbę cyfr w liczbie całkowitej?
Odpowiedzi:
Jeśli chcesz, aby liczba całkowita była równa liczbie cyfr w liczbie całkowitej, zawsze możesz przekonwertować ją na ciąg znaków str(133)
i znaleźć jej długość len(str(123))
.
Math.log10
metoda trwało tylko 7.486343383789062e-05 sekund, około 1501388 razy szybciej!
Math.log10
zamiast tego.
Bez konwersji na ciąg
import math
digits = int(math.log10(n))+1
Do obsługi liczb zerowych i ujemnych
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 '-'
Prawdopodobnie chciałbyś umieścić to w funkcji :)
Oto kilka punktów odniesienia. len(str())
Ma już za sobą nawet dla bardzo małych ilościach
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
do 99999999999999999999999999999999999999999999999999999999999999999999999
( 71 dziewiątek ) zwraca 72 ? Myślałem, że mogę polegać na metodzie log10, ale zamiast tego muszę użyć len (str (x)) :(
math.log10(999999999999999)
jest równy 14.999999999999998
tak się int(math.log10(999999999999999))
staje 14
. Ale wtedy math.log10(9999999999999999)
jest równy 16.0
. Być może używanie round
jest rozwiązaniem tego problemu.
math.log10 jest szybki, ale stwarza problem, gdy liczba jest większa niż 99999999999999997. Jest tak, ponieważ liczba zmiennoprzecinkowa ma zbyt wiele .9s, co powoduje zaokrąglenie wyniku w górę.
Rozwiązaniem jest użycie metody licznika while dla liczb powyżej tego progu.
Aby uczynić to jeszcze szybszym, utwórz 10 ^ 16, 10 ^ 17 itd. I zapisz jako zmienne na liście. W ten sposób przypomina wyszukiwanie tabeli.
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
. Ciekawie jest zobaczyć, jak reprezentacja binarna zmienia wartości, dając matematycznie niepoprawny wynik.
Python 2.*
int
zajmuje 4 lub 8 bajtów (32 lub 64 bity), w zależności od kompilacji Pythona. sys.maxint
( 2**31-1
dla 32-bitowych liczb całkowitych, 2**63-1
dla 64-bitowych liczb całkowitych) powie ci, która z dwóch możliwości jest dostępna.
W Pythonie 3 int
s (podobnie jak long
w Pythonie 2) może przyjmować dowolne rozmiary do ilości dostępnej pamięci; sys.getsizeof
daje wskazówkę dobre dla danej wartości, choć ma również liczyć jakiś stały narzut:
>>> import sys
>>> sys.getsizeof(0)
12
>>> sys.getsizeof(2**99)
28
Jeśli, jak sugerują inne odpowiedzi, myślisz o jakimś ciągu reprezentującym wartość całkowitą, to po prostu weź len
tę reprezentację, czy to w bazie 10, czy w inny sposób!
Minęło kilka lat, odkąd zadano to pytanie, ale opracowałem punkt odniesienia dla kilku metod obliczania długości liczby całkowitej.
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
(funkcja libc wymaga pewnej konfiguracji, której nie zawarłem)
size_exp
to dzięki Brianowi Preslopsky'emu, size_str
to dzięki GeekTantrze i size_math
dzięki Johnowi La Rooyowi
Oto wyniki:
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)
(Zastrzeżenie: funkcja działa na wejściach od 1 do 1 000 000)
Oto wyniki sys.maxsize - 100000
do 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)
Jak widać, mod_size
( len("%i" % i)
) jest najszybszy, nieco szybszy niż używanie str(i)
i znacznie szybszy niż inne.
libc = ctyle.CDLL('libc.so.6', use_errno=True)
(zgadując, że to jest to). I to nie działa dla liczb większych niż sys.maxsize
ponieważ liczby zmiennoprzecinkowe nie mogą być „bardzo duże”. Więc każda liczba powyżej tego, myślę, że utknąłeś z jedną z wolniejszych metod.
Niech liczba będzie n
wtedy liczbą cyfr n
podaną przez:
math.floor(math.log10(n))+1
Zauważ, że da to prawidłowe odpowiedzi dla liczb całkowitych + ve <10e15. Poza tym limity precyzji typu zwrotu math.log10
zaczynają się, a odpowiedź może być wyłączona o 1. Chciałbym po prostu użyć len(str(n))
tego; wymaga to O(log(n))
czasu, który jest taki sam, jak iteracja po potęgach 10.
Dzięki @SetiVolkylany za zwrócenie mojej uwagi na to ograniczenie. To niesamowite, jak pozornie poprawne rozwiązania mają zastrzeżenia w szczegółach implementacji.
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
. Spójrz na moją odpowiedź stackoverflow.com/a/42736085/6003870 .
Policz liczbę cyfr bez konwersji liczby całkowitej na ciąg:
x=123
x=abs(x)
i = 0
while x >= 10**i:
i +=1
# i is the number of digits
Jak wspomniano, drogi użytkowniku @Calvintwr, funkcja math.log10
ma problem z liczbą spoza zakresu [-999999999999997, 99999999999999997], w której występują błędy zmiennoprzecinkowe. Miałem ten problem z JavaScript (Google V8 i NodeJS) i C (kompilator GNU GCC), więc 'purely mathematically'
rozwiązanie jest tutaj niemożliwe.
Na podstawie tego GIST i odpowiedzi kochany użytkownika @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
Przetestowałem to na liczbach o długości do 20 (włącznie) i wszystko w porządku. Musi to wystarczyć, ponieważ maksymalna liczba całkowita w systemie 64-bitowym wynosi 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
Wszystkie przykłady kodów testowanych w Pythonie 3.5
Dla potomnych, bez wątpienia najwolniejsze rozwiązanie tego problemu:
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
Zakładając, że pytasz o największą liczbę, jaką możesz zapisać w liczbie całkowitej, wartość zależy od implementacji. Sugeruję, abyś nie myślał w ten sposób, używając Pythona. W każdym razie całkiem spora wartość może być przechowywana w pythonowej „liczbie całkowitej”. Pamiętaj, że Python używa pisania kaczego!
Edycja: Udzieliłem odpowiedzi przed wyjaśnieniem, że pytający chciał liczby cyfr. W tym celu zgadzam się z metodą sugerowaną przez przyjętą odpowiedź. Nic więcej do dodania!
def length(i):
return len(str(i))
Można to zrobić szybko dla liczb całkowitych, używając:
len(str(abs(1234567890)))
Który pobiera długość ciągu wartości bezwzględnej „1234567890”
abs
zwraca liczbę BEZ jakichkolwiek negatywów (tylko wielkość liczby), str
rzutuje / konwertuje ją na ciąg znaków i len
zwraca długość łańcucha tego ciągu.
Jeśli chcesz, aby działał dla liczb zmiennoprzecinkowych, możesz użyć jednej z następujących opcji:
# Ignore all after decimal place
len(str(abs(0.1234567890)).split(".")[0])
# Ignore just the decimal place
len(str(abs(0.1234567890)))-1
Dla przyszłego odniesienia.
int
) niż skrócić jej reprezentację ciągu dziesiętnego: len(str(abs(int(0.1234567890))))
zwraca 1.
Sformatuj w notacji naukowej i odłóż wykładnik:
int("{:.5e}".format(1000000).split("e")[1]) + 1
Nie wiem o prędkości, ale to proste.
Zwróć uwagę na liczbę cyfr znaczących po przecinku („5” w „.5e” może być problemem, jeśli zaokrągla w górę dziesiętną część notacji naukowej do innej cyfry. Ustawiam ją dowolnie dużą, ale może odzwierciedlać długość największej liczby, o której wiesz.
def count_digit(number):
if number >= 10:
count = 2
else:
count = 1
while number//10 > 9:
count += 1
number = number//10
return count
Jeśli musisz poprosić użytkownika o podanie danych, a następnie musisz policzyć, ile jest liczb, możesz to zrobić:
count_number = input('Please enter a number\t')
print(len(count_number))
Uwaga: Nigdy nie bierz int jako danych wejściowych użytkownika.
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
Mój kod do tego samego wygląda następująco; użyłem metody log10:
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
Musiałem określić w przypadku 1 i 0, ponieważ log10 (1) = 0 i log10 (0) = ND, a zatem wspomniany warunek nie jest spełniony. Jednak ten kod działa tylko dla liczb całkowitych.
Oto obszerna, ale szybka wersja:
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
Tylko 5 porównań dla niezbyt dużych liczb. Na moim komputerze jest to około 30% szybsza niż math.log10
wersja i 5% szybsza niż ta len( str())
. Ok ... nie tak atrakcyjny, jeśli nie użyjesz go wściekle.
A oto zestaw liczb, których użyłem do przetestowania / zmierzenia mojej funkcji:
n = [ int( (i+1)**( 17/7. )) for i in xrange( 1000000 )] + [0,10**16-1,10**16,10**16+1]
Uwaga: nie zarządza liczbami ujemnymi, ale dostosowanie jest łatwe ...
>>> a=12345
>>> a.__str__().__len__()
5
len(str(a))
.