web-dev-qa-db-ja.com

Pythonの整数の長さ

Pythonでは、整数の桁数をどのように見つけますか?

182
Strigoides

整数の桁数のように整数の長さが必要な場合は、いつでもstr(133)のような文字列に変換し、len(str(123))のようにその長さを見つけることができます。

235
GeekTantra

文字列に変換しない

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

すべてのmath.log10ソリューションはあなたに問題を与えるでしょう。

math.log10は速いですがあなたの数が999999999999997よりも大きいとき問題を生じます。これはfloatが多すぎる.9sを持っているために結果が切り上げられる原因となります。

解決策は、そのしきい値を超える数値に対して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
30
Calvintwr

Pythonのビルドに応じて、Pythonの2.*intsには4バイトまたは8バイト(32または64ビット)が必要です。 sys.maxint(32ビット整数の場合は2**31-1、64ビット整数の場合は2**63-1)は、2つの可能性のどちらが得られるかを教えてくれます。

Python 3では、(Python 2のintsのように)longsは、最大で利用可能なメモリの量まで任意のサイズを取ることができます。 sys.getsizeofは与えられた値の良い目安を与えてくれますが、は固定されたオーバーヘッドも数えます:

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

他の回答が示唆するように、整数値の何らかの文字列表現を考えているのなら、その表現のlenを10進数かそれ以外のものにしてください。

21
Alex Martelli

数をnとすると、nの桁数は次のようになります。

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

これは10個以上15以下の整数の正解を与えることに注意してください。それを超えると、math.log10の戻り値の型の精度の限界が現れて、答えが1だけずれてしまう可能性があります。それを超えてlen(str(n))を使用します。これはO(log(n))時間を必要とし、これは10のべき乗で反復するのと同じです。

私の注意をこの制限にもたらしてくれた@SetiVolkylanyに感謝します。その驚くべきどのように正しい解決策が実装の詳細で警告を持っています。

13
BiGYaN

文字列に変換せずに、次のようにします。

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

    x = abs(x)

    if x < 10:
        return 1

    return 1 + lenDigits(x / 10)

ミニマリスト再帰FTW

13
odradek

親愛なるユーザー@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でテストされたコードのすべての例

5
Seti Volkylany

この質問がされてから数年が経ちましたが、整数の長さを計算するためのいくつかの方法のベンチマークをまとめました。

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から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_sizelen("%i" % i))は最も速く、str(i)を使用するよりもわずかに速く、他のものよりもかなり高速です。

4
NoOneIsHere

後世のために、間違いなくこの問題に対する最も遅い解決策:

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

これは、整数を使ってすばやく行うことができます。

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

今後の参考のために。

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

整数に格納できる最大の数を求めていると仮定すると、その値は実装に依存します。私はあなたがpythonを使うときあなたがそのように考えないことを勧めます。いずれにせよ、かなり大きな値をPythonの 'integer'に格納することができます。 Pythonはダックタイピングを使用しています。

編集:質問者が桁数を求めていることを明確にする前に答えを述べました。そのために、私は受け入れられた答えによって提案された方法に同意します。追加するものはこれ以上ありません。

1
batbrat

科学的記数法でフォーマットして指数を引き抜く:

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

速度についてはわかりませんが、簡単です。

小数点以下の有効桁数に注意してください( "。5e"の "5"は、科学表記の小数部を別の桁に切り上げると問題になることがあります。私はそれを任意に大きく設定しましたが、あなたが知っている最大の数の長さ。

0

整数を文字列に変換せずに桁数を数えます。

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