Python'da, bir tamsayıdaki basamak sayısını nasıl bulursunuz?
Python'da, bir tamsayıdaki basamak sayısını nasıl bulursunuz?
Yanıtlar:
Bir tamsayı uzunluğunun tamsayıdaki hane sayısında olduğu gibi olmasını istiyorsanız, onu her zaman dizeye dönüştürebilir str(133)
ve uzunluğunu bulabilirsiniz len(str(123))
.
Math.log10
yöntem sadece 7.486343383789062e-05 saniye sürdü , yaklaşık 1501388 kat daha hızlı!
Math.log10
.
Dizeye dönüşüm olmadan
import math
digits = int(math.log10(n))+1
Sıfır ve negatif sayıları da ele almak için
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 '-'
Muhtemelen bir fonksiyona koymak istersiniz :)
İşte bazı kriterler. len(str())
Hatta oldukça küçük sayılar için geride zaten
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
için 99999999999999999999999999999999999999999999999999999999999999999999999
( 71 dokuzlu döndürür) 72 ? Log10 yöntemine güvenebileceğimi düşündüm ama bunun yerine len (str (x)) kullanmalıyım :(
math.log10(999999999999999)
eşittir 14.999999999999998
çok int(math.log10(999999999999999))
olur 14
. Ama sonra math.log10(9999999999999999)
eşittir 16.0
. Belki de kullanmak round
bu soruna bir çözümdür.
math.log10 hızlıdır ancak sayınız 999999999999997'den büyük olduğunda sorun çıkarır. Bunun nedeni, kayan noktanın çok fazla .9 olması ve sonucun yuvarlanmasına neden olmasıdır.
Çözüm, bu eşiğin üzerindeki sayılar için while sayacı yöntemi kullanmaktır.
Bunu daha da hızlı yapmak için, 10 ^ 16, 10 ^ 17 vb. Oluşturun ve bir listede değişken olarak saklayın. Bu şekilde, tablo araması gibidir.
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
. İkili gösterimin değerleri matematiksel olarak yanlış sonuç vererek nasıl çevirdiğini görmek ilginçtir.
Python'lar 2.*
int
, Python derlemenize bağlı olarak 4 veya 8 bayt (32 veya 64 bit) alır. sys.maxint
( 2**31-1
32 bit girişler 2**63-1
için, 64 bit girişler için) size iki olasılıktan hangisinin elde edildiğini söyleyecektir.
Python 3'te, int
s ( long
Python 2'deki s gibi ) kullanılabilir bellek miktarına kadar keyfi boyutlar alabilir; sys.getsizeof
o halde, size herhangi bir değeri için iyi bir gösterge verir vermez de bazı sabit yükü saymak:
>>> import sys
>>> sys.getsizeof(0)
12
>>> sys.getsizeof(2**99)
28
Diğer yanıtların da belirttiği gibi, tamsayı değerinin dize temsilini düşünürseniz, len
o temsili 10 ya da başka şekilde temsil edin!
Bu sorunun sorulmasından bu yana birkaç yıl geçti, ancak bir tamsayının uzunluğunu hesaplamak için çeşitli yöntemlerin bir ölçütünü derledim.
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
(libc işlevi dahil etmediğim bazı kurulumlar gerektirir)
size_exp
Brian Preslopsky size_str
sayesinde, GeekTantra size_math
sayesinde ve John La Rooy sayesinde
Sonuçlar burada:
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)
(Sorumluluk reddi: fonksiyon 1 ila 1.000.000 girişlerde çalıştırılır)
İşte için sonuçları sys.maxsize - 100000
için 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)
Gördüğünüz gibi, mod_size
( len("%i" % i)
) en hızlı, kullanmaktan biraz daha hızlı str(i)
ve diğerlerinden daha hızlı.
libc = ctyle.CDLL('libc.so.6', use_errno=True)
(tahmin etmek budur). Ve daha büyük sayılar için çalışmıyor sys.maxsize
kayan nokta sayıları "çok büyük" olamaz çünkü. Bunun üzerinde herhangi bir sayı, sanırım daha yavaş yöntemlerden biri ile sıkışmış.
Sayısı olsun n
basamak daha sonra sayı n
ile elde edilir:
math.floor(math.log10(n))+1
Bunun + ve tamsayılar <10e15 için doğru cevaplar vereceğini unutmayın. Bunun ötesinde dönüş tipinin hassas limitleri math.log10
devreye girer ve cevap 1'de olabilir. Sadece bunun len(str(n))
ötesinde kullanırdım; bu gerektirirO(log(n))
10'lu güçlerin tekrarlanmasıyla aynı zaman .
@SetiVolkylany'a bu kısıtlamaya katıldığım için teşekkürler. Görünüşte doğru çözümlerin uygulama detaylarında dikkat edilmesi şaşırtıcı.
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
. Cevabım bak stackoverflow.com/a/42736085/6003870 .
Tamsayıyı bir dizeye dönüştürmeden basamak sayısını sayın:
x=123
x=abs(x)
i = 0
while x >= 10**i:
i +=1
# i is the number of digits
Sevgili kullanıcı @ Calvintwr'den bahsedildiği gibi, fonksiyonun math.log10
kayan nokta hataları aldığımız bir aralığın [-999999999999997, 999999999999997] dışında bir sayıda problemi vardır. JavaScript (Google V8 ve NodeJS) ve C (GNU GCC derleyicisi) ile bu sorunu yaşadım, bu yüzden 'purely mathematically'
burada bir çözüm imkansız.
Bu özü ve cevabı esas alan sevgili @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
Uzunluğu 20 (dahil) ve tamam olan sayılar üzerinde test ettim. Bu yeterli olmalı, çünkü 64 bit sistemdeki uzunluk maksimum tamsayı sayısı 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
Python 3.5 ile test edilen tüm kod örnekleri
Gelecek nesiller için şüphesiz bu soruna en yavaş çözüm:
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
Bir tamsayıda saklayabileceğiniz en büyük sayıyı istediğinizi varsayarsak, değer uygulamaya bağlıdır. Python kullanırken böyle düşünmemenizi öneririm. Her durumda, bir python 'tamsayı' içinde oldukça büyük bir değer saklanabilir. Unutma, Python ördek yazmayı kullanıyor!
Edit: Ben cevap rakam asker sayısını istedi açıklama önce verdim. Bunun için kabul edilen cevabın önerdiği yönteme katılıyorum. Eklenecek başka bir şey yok!
def length(i):
return len(str(i))
Tamsayılar için aşağıdakiler kullanılarak hızlı bir şekilde yapılabilir:
len(str(abs(1234567890)))
Hangi "1234567890" mutlak değerinin dizesinin uzunluğunu alır
abs
negatif olmayan sayıyı (yalnızca sayının büyüklüğünü) döndürür, str
bir dizgeye çevirir / dönüştürür velen
döndürür, bu dizenin dize uzunluğunu döndürür.
Şamandıralar için çalışmasını istiyorsanız, aşağıdakilerden birini kullanabilirsiniz:
# Ignore all after decimal place
len(str(abs(0.1234567890)).split(".")[0])
# Ignore just the decimal place
len(str(abs(0.1234567890)))-1
İleride başvurmak için.
int
ondalık dize temsilini kısaltmak için giriş numarasını kendisi (örneğin bir döküm ile ) kısaltmak için daha basit olacağını düşünüyorum : 1 len(str(abs(int(0.1234567890))))
döner.
Bilimsel gösterimde biçimlendirin ve üssü koparın:
int("{:.5e}".format(1000000).split("e")[1]) + 1
Hızı bilmiyorum, ama bu basit.
Lütfen ondalık basamaktan sonraki önemli basamakların sayısına dikkat edin (".5e" deki "5", bilimsel gösterimin ondalık kısmını başka bir rakama yuvarlarsa bir sorun olabilir. bildiğiniz en büyük sayının uzunluğu.
def count_digit(number):
if number >= 10:
count = 2
else:
count = 1
while number//10 > 9:
count += 1
number = number//10
return count
Bir kullanıcıdan giriş vermesini istemeniz gerekiyorsa ve orada kaç sayı olduğunu saymanız gerekiyorsa, bunu takip edebilirsiniz:
count_number = input('Please enter a number\t')
print(len(count_number))
Not: Kullanıcı girişi olarak asla int kullanmayın.
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
Aynı benim kod aşağıdaki gibidir; ben log10 yöntemini kullandık:
from math import *
def digit_count (sayı):
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
Log10 (1) = 0 ve log10 (0) = ND olduğu için 1 ve 0 durumunda belirtmek zorunda kaldım ve dolayısıyla belirtilen koşul karşılanmadı. Ancak, bu kod yalnızca tam sayılar için çalışır.
İşte hantal ama hızlı bir sürüm:
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
Çok büyük sayılar için sadece 5 karşılaştırma. Bilgisayarımda math.log10
sürümden yaklaşık% 30 daha hızlı ve sürümden% 5 daha hızlılen( str())
. Tamam ... öfkeyle kullanmazsan çok çekici olmaz.
İşte fonksiyonumu test etmek / ölçmek için kullandığım sayılar kümesi:
n = [ int( (i+1)**( 17/7. )) for i in xrange( 1000000 )] + [0,10**16-1,10**16,10**16+1]
Not: negatif sayıları yönetmez, ancak adaptasyon kolaydır ...
>>> a=12345
>>> a.__str__().__len__()
5
len(str(a))
.