回答:
整数の長さを整数の桁数のようにしたい場合は、常にそれを文字列のように変換し、のようにstr(133)
その長さを見つけることができますlen(str(123))
。
Math.log10
メソッドにかかった時間はわずか 7.486343383789062e-05秒で、約1501388倍高速です。
Math.log10
代わりに使用してください。
文字列への変換なし
import math
digits = int(math.log10(n))+1
ゼロと負の数値も処理するには
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 '-'
あなたはおそらくそれを関数に入れたいでしょう:)
ここにいくつかのベンチマークがあります。len(str())
でも、かなり少数のための後ろに既にあります
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
を教えてください。log10メソッドを信頼できると思ったが、代わりにlen(str(x))を使用する必要がある:(99999999999999999999999999999999999999999999999999999999999999999999999
math.log10(999999999999999)
等しくなる14.999999999999998
ようにint(math.log10(999999999999999))
なりました14
。しかし、次にmath.log10(9999999999999999)
等しい16.0
です。多分使用round
することはこの問題の解決策です。
math.log10は高速ですが、数値が999999999999997より大きい場合に問題が発生します。これは、フロートの.9が多すぎて、結果が切り上げられるためです。
解決策は、そのしきい値を超える数値に対してwhileカウンターメソッドを使用することです。
これをさらに速くするには、10 ^ 16、10 ^ 17などを作成し、変数としてリストに格納します。そのように、それはテーブルルックアップのようなものです。
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
。バイナリ表現が値を反転させて数学的に正しくない結果を与える方法を見るのは興味深いです。
Python 2.*
int
は、Pythonビルドに応じて、4または8バイト(32または64ビット)のいずれかを使用します。 sys.maxint
(2**31-1
32ビット整数の場合、2**63-1
、64ビット整数の場合)は、2つの可能性のどちらが得られるかを通知します。
Python 3では、int
s(long
Python 2のsと同様)は使用可能なメモリの量まで任意のサイズをとることができます。sys.getsizeof
それはあるが、あなたに任意の値が良い指標を与えないにもいくつかの固定オーバーヘッドを数えます:
>>> import sys
>>> sys.getsizeof(0)
12
>>> sys.getsizeof(2**99)
28
他の答えが示唆しているように、整数値の文字列表現について考えている場合はlen
、その表現をそのまま使用してください。10進数かそれ以外の場合も同様です。
この質問が出されてから数年になりますが、整数の長さを計算するいくつかの方法のベンチマークをまとめました。
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関数にはいくつかの設定が必要ですが、これは含まれていません)
size_exp
Brian Preslopsky、size_str
GeekTantra、そしてsize_math
John La Rooyに感謝します
結果は次のとおりです。
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)
(免責事項:関数は入力1から1,000,000で実行されます)
sys.maxsize - 100000
to の結果は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)
ご覧のとおり、mod_size
(len("%i" % i)
)が最も速く、使用よりもわずかにstr(i)
速く、他よりも大幅に高速です。
libc = ctyle.CDLL('libc.so.6', use_errno=True)
(これがそうだと思います)。またsys.maxsize
、浮動小数点数を「非常に大きく」することはできないため、それ以上の数では機能しません。したがって、それ以上の数の場合、遅い方法の1つに行き詰まっていると思います。
その数n
をそのときの桁数とn
すると:
math.floor(math.log10(n))+1
これは、+ ve整数<10e15に対して正しい答えを与えることに注意してください。キックインの戻り値の型の精度の制限math.log10
と答えが1ずれる可能性があることlen(str(n))
を超えて、私は単にそれを超えて使用します。これにはO(log(n))
10の累乗を反復するのと同じ時間が必要です。
この制限に注意を払ってくれた@SetiVolkylanyに感謝します。一見正しいソリューションが実装の詳細に注意を払っている驚くべきこと。
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
。私の答えstackoverflow.com/a/42736085/6003870を見てください。
整数を文字列に変換せずに桁数を数えます:
x=123
x=abs(x)
i = 0
while x >= 10**i:
i +=1
# i is the number of digits
親愛なるユーザー@Calvintwrについて述べたように、関数にmath.log10
は[-999999999999997、999999999999997]の範囲外の数値で問題があり、浮動小数点エラーが発生します。JavaScript(Google V8とNodeJS)とC(GNU GCCコンパイラ)でこの問題が発生したため、'purely mathematically'
解決策はありません。
この要点と回答に基づいて、親愛なるユーザー@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
私は、長さが最大20(両端を含む)で問題ない数値でテストしました。64ビットシステムでの整数の最大長は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でテストされたコードのすべての例
後世のために、間違いなくこの問題の最も遅い解決策:
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
def length(i):
return len(str(i))
次のコマンドを使用すると、整数をすばやく処理できます。
len(str(abs(1234567890)))
「1234567890」の絶対値の文字列の長さを取得します
abs
負の数なしで数値を返し(数値の大きさのみ)、str
それを文字列にキャスト/変換し、len
その文字列の長さを返します。
フロートで機能させる場合は、次のいずれかを使用できます。
# Ignore all after decimal place
len(str(abs(0.1234567890)).split(".")[0])
# Ignore just the decimal place
len(str(abs(0.1234567890)))-1
今後の参考のために。
int
10進数の文字列表現を切り捨てるよりも、入力番号自体を切り捨てるほうが(たとえば、へのキャストを使用して)簡単len(str(abs(int(0.1234567890))))
です:1を返します
科学表記法でフォーマットし、指数を引き抜きます。
int("{:.5e}".format(1000000).split("e")[1]) + 1
速度はわかりませんが、簡単です。
小数点以下の有効桁数に注意してください( ".5e"の "5"は、科学表記の小数部を別の桁に切り上げる場合に問題となる可能性があります。任意に大きく設定しましたが、あなたが知っている最大の数の長さ。
def count_digit(number):
if number >= 10:
count = 2
else:
count = 1
while number//10 > 9:
count += 1
number = number//10
return count
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
同じための私のコードは次のとおりです;私はlog10メソッドを使用しました:
from math import *
def digit_count(数値):
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およびlog10(0)= NDであり、前述の条件が満たされていないため、1と0の場合を指定する必要がありました。ただし、このコードは整数に対してのみ機能します。
これはかさばるが速いバージョンです:
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
大きすぎない数の比較は5つだけです。私のコンピューターでは、math.log10
バージョンより約30%高速で、バージョンより5%高速です。len( str())
。わかりました...猛烈に使わなければ、それほど魅力的ではありません。
そして、これが私の機能をテスト/測定するために使用した一連の数値です:
n = [ int( (i+1)**( 17/7. )) for i in xrange( 1000000 )] + [0,10**16-1,10**16,10**16+1]
注意:負の数は管理しませんが、適応は簡単です...
>>> a=12345
>>> a.__str__().__len__()
5
len(str(a))
ます。