Pythonの整数の長さ


233

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


1
質問が理解できません。整数のサイズを意味しましたか?桁数を調べますか?どうか明らかにしてください。
batbrat

回答:


317

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


18
もちろん、桁数を探している場合、負の符号を数えるため、負の数には大きすぎる結果が生成されます。
Chris Upchurch、

37
ねえ、これは遅いソリューションです。私はランダムな6桁の数値の階乗を行い、その長さを見つけました。このメソッドは95.891秒かかりました。また、Math.log10メソッドにかかった時間はわずか 7.486343383789062e-05秒で、約1501388倍高速です。
FadedCoder 2017年

1
これは単に遅いだけでなく、メモリをかなり消費し、多数の場合に問題を引き起こす可能性があります。Math.log10代わりに使用してください。
ペイマン

246

文字列への変換なし

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

5
これにlog10を使用することは、数学者の解決策です。len(str())の使用はプログラマのソリューションであり、より明確で簡単です。
Glenn Maynard

68
@Glenn:確かに、これが悪い解決策であることを示唆していないことを願っています。プログラマーの素朴なO(log10 n)ソリューションは、アドホックなプロトタイピングコードで適切に機能します。ニブラーの+1。
ジュリエット

5
@gnibbler:+1。log10が数値の大きさを見つけるために使用できることを決して理解していません。私はもう一度投票することを望みます:)
Abbas

14
こんにちは!(71ナイン)が72を返す理由int(math.log10(x)) +1を教えてください。log10メソッドを信頼できると思ったが、代わりにlen(str(x))を使用する必要がある:(99999999999999999999999999999999999999999999999999999999999999999999999
Marecky

6
私は奇妙な振る舞いの理由を知っていると思います、それは浮動小数点の不正確さが原因です。math.log10(999999999999999)等しくなる14.999999999999998ようにint(math.log10(999999999999999))なりました14。しかし、次にmath.log10(9999999999999999)等しい16.0です。多分使用roundすることはこの問題の解決策です。
jamylak 2012

43

すべてのmath.log10ソリューションで問題が発生します。

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。バイナリ表現が値を反転させて数学的に正しくない結果を与える方法を見るのは興味深いです。
WloHu

その後、len(str(num))の方が良いでしょう
Vighnesh Raut

2
@Vighnesh Raut:そしてマグニチュードがより遅い
Chaitanya Bangera

「正確な結果を得るために浮動小数点演算に依存することは危険です」-コアPython開発チームのメンバーであるMark Dickinson bugs.python.org/issue3724
Sreeragh AR

26

Python 2.* intは、Pythonビルドに応じて、4または8バイト(32または64ビット)のいずれかを使用します。 sys.maxint2**31-132ビット整数の場合、2**63-1、64ビット整数の場合)は、2つの可能性のどちらが得られるかを通知します。

Python 3では、ints(longPython 2のsと同様)は使用可能なメモリの量まで任意のサイズをとることができます。sys.getsizeofそれはあるが、あなたに任意の値が良い指標を与えないにもいくつかの固定オーバーヘッドを数えます:

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

他の答えが示唆しているように、整数値の文字列表現について考えている場合はlen、その表現をそのまま使用してください。10進数かそれ以外の場合も同様です。


申し訳ありませんが、この回答はマイナスになりました。これは有益であり、質問のもっともらしい点に当てはまります(どの「len」が望ましいかについてより具体的である場合のみ)。+1
mjv

これは興味深いようですが、長さを抽出する方法がわかりません
Tjorriemorrie

17

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

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_expBrian Preslopsky、size_strGeekTantra、そして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 - 100000to の結果は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)速く、他よりも大幅に高速です。


あなたは本当にlibc設定を含めるべきですlibc = ctyle.CDLL('libc.so.6', use_errno=True)(これがそうだと思います)。またsys.maxsize、浮動小数点数を「非常に大きく」することはできないため、それ以上の数では機能しません。したがって、それ以上の数の場合、遅い方法の1つに行き詰まっていると思います。
トルク

15

その数nをそのときの桁数とnすると:

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

これは、+ ve整数<10e15に対して正しい答えを与えることに注意してください。キックインの戻り値の型の精度の制限math.log10と答えが1ずれる可能性があることlen(str(n))を超えて、私は単にそれを超えて使用します。これにはO(log(n))10の累乗を反復するのと同じ時間が必要です。

この制限に注意を払ってくれた@SetiVolkylanyに感謝します。一見正しいソリューションが実装の詳細に注意を払っている驚くべきこと。


1
nが[-999999999999997、999999999999997]の範囲外の場合は機能しません
PADYMKO

@SetiVolkylany、私はpython2.7と3.5で50桁までテストしました。ただassert list(range(1,51)) == [math.floor(math.log10(n))+1 for n in (10**e for e in range(50))]
BiGYaN 2017年

2
Python2.7またはPython3.5で試してください>>> math.floor(math.log10(999999999999997))+1 15.0 >>> math.floor(math.log10(999999999999998))+1 16.0。私の答えstackoverflow.com/a/42736085/6003870を見てください。
PADYMKO 2017年

12

まあ、文字列に変換せずに私は次のようなことをします:

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

    x = abs(x)

    if x < 10:
        return 1

    return 1 + lenDigits(x / 10)

ミニマリストの再帰FTW


1
多数の場合、再帰制限に達します。
nog642

9

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

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

ニースのものは文字列変換を完全に避けます。
Patrick Mutuku、

8

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


3

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

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)


1

整数に格納できる最大数を要求していると仮定すると、値は実装に依存します。Pythonを使用するときは、そのように考えないことをお勧めします。いずれにせよ、非常に大きな値をPythonの「整数」に格納できます。Pythonはダックタイピングを使用することを忘れないでください!

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


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

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

今後の参考のために。


int10進数の文字列表現を切り捨てるよりも、入力番号自体を切り捨てるほうが(たとえば、へのキャストを使用して)簡単len(str(abs(int(0.1234567890))))です:1を返します
David Foerster

いいえ、それはうまくいきません。0.17を整数に変換すると、0が返され、その長さは0.17の長さとは異なります
Frogboxe

最初のケースでは、文字列表現から小数点以下を切り捨てることで、数値の整数部分の長さを効果的に計算しています。これも私の提案です。0.17の場合は、両方のソリューションは、1を返す
デビッド・フェルスター

0

科学表記法でフォーマットし、指数を引き抜きます。

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

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

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


0
def count_digit(number):
  if number >= 10:
    count = 2
  else:
    count = 1
  while number//10 > 9:
    count += 1
    number = number//10
  return count

このコードは問題を解決する可能性がありますが、これが問題を解決する方法と理由の説明含めると、投稿の品質が向上し、投票数が増える可能性があります。あなたが今尋ねている人だけでなく、あなたが将来の読者のための質問に答えていることを忘れないでください。回答を編集して説明を追加し、適用される制限と前提を示してください。
Adrian Mole

0

ユーザーに入力を要求する必要があり、そこにいくつの数字があるかを数える必要がある場合は、次のようにすることができます。

count_number = input('Please enter a number\t')

print(len(count_number))

注:intをユーザー入力として使用しないでください。


文字列の長さに実際に関連しているため、ここで説明するかなり具体的なケース。また、数字以外の任意の文字を入力することもできますが、それでも数字であると信じられます。
ベン

0
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

0

同じための私のコードは次のとおりです;私は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の場合を指定する必要がありました。ただし、このコードは整数に対してのみ機能します。


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]

注意:負の数は管理しませんが、適応は簡単です...


-13
>>> a=12345
>>> a.__str__().__len__()
5

6
特別なメソッドを直接呼び出さないでください。書かれていlen(str(a))ます。
マイクグラハム、

8
@ ghostdog74電気ソケットがあるからといって、指を差し込む必要があるわけではありません。

3
それであなたがそれに反対しているなら、なぜそれを使うのが間違っているのか教えてくれませんか?
ghostdog74 2010

11
"Magic" __メソッドは、コードを直接呼び出すためではなく、Python内部から呼び出すためのものです。それはハリウッドフレームワークのパターンです。私たちに電話しないでください。私たちはあなたに電話します。しかし、このフレームワークの目的は、これらが標準のPython組み込み関数が利用する魔法のメソッドであることです。これにより、クラスは組み込み関数の動作をカスタマイズできます。コードが直接呼び出すメソッドの場合は、メソッドに「__」以外の名前を付けます。これにより、プログラマーの消費を目的としたメソッドと、Python組み込みからのコールバック用に提供されたメソッドが明確に区別されます。
PaulMcG 2010

7
既知のユニバースの他の誰もが str()とlen()を使用するため、これは悪い考えです。これは異なるために異なることであり、本質的に悪いことです-言うまでもなく、それは地獄のように醜いだけです。-1。
Glenn Maynard
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.