Pythonで非常に大きな数を処理する


139

私はPythonでのポーカーハンドの高速評価を検討しています。プロセスをスピードアップする1つの方法は、すべてのカードの面とスートを素数として表し、それらを掛け合わせて手を表すことだと思いました。聖霊降臨祭に:

class PokerCard:
    faces = '23456789TJQKA'
    suits = 'cdhs'
    facePrimes = [11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 53, 59, 61]
    suitPrimes = [2, 3, 5, 7]

そして

    def HashVal(self):
      return PokerCard.facePrimes[self.cardFace] * PokerCard.suitPrimes[self.cardSuit]

これは、各手に数値を与え、モジュロを介して、手にある王の数またはハートの数を教えてくれます。たとえば、その中に5つ以上のクラブがあるハンドは、2 ^ 5で均等に分割されます。4人のキングがいるハンドは、59 ^ 4で均等に分割されます。

問題は、AcAdAhAsKdKhKsのような7枚のカードの手持ちのハッシュ値が約62.7兆であり、内部で表現するために32ビットよりもかなり多くかかることです。そのような大きな数値をPythonに保存して、算術演算を実行できるようにする方法はありますか?


13
この方法でデータを表現し始めても、速度が大幅に向上することを確信していますか?これはあなたの質問には答えないが、それでもなお..
Thomi

3
カードの値と表現に別々の変数を使用する代わりに、辞書を使用することを提案します。(したがって、面= {'2':11、 '3':13、 '4':17、 '5':19、 '6':23、 '7':29、 '8':31、 '9' :37、 'T':41、 'J':43、 'Q':53、 'K':59、 'A':61}とスート= {'c':2、 'd':3、 ' h ':5、' s ':7}。)
JAB

回答:


176

Pythonは、「bignum」整数型をサポートしており、任意の大きな数値を処理できます。Python 2.5以降では、このタイプが呼び出されlong、タイプとは異なりintますが、インタープリターはどちらか適切な方を自動的に使用します。Python 3.0以降では、int型は完全に削除されています。

ただし、これは単なる実装の詳細です。バージョン2.5以降であれば、標準の数学演算を実行するだけで、32ビット数学の境界を超える数値は自動的に(そして透過的に)bignumに変換されます。

あなたはPEP 0237ですべての悲惨な詳細を見つけることができます。


2
問題は、32ビット整数の代わりにbignumを使用することによるパフォーマンスヒットが、彼が使用している手の評価の賢い方法によるパフォーマンスの利点を上回っているかどうかです。
Chris Upchurch、

3
実際、intとlongの境界は2.5で破られました。3.0ではintが完全に削除され、longが唯一の整数型になります。
イグナシオバスケスエイブラムス

1
大きな数字はどれくらいですか?PHI ^ 4000000になりますか?
Mike Caron、

9
@Mike Caron — PEP 0237にリストされている構造体が正確である場合、longsの長さ(数字)は、最大4,294,967,295桁の符号なし32ビット整数として格納されます。つまり、φ**(4 * 10 ** 6 )、これは832,951桁のみです。ただし、φは整数ではないため、数値を計算するにはDecimal(Pythonの浮動小数点bignum)を使用する必要があります。longただし、結果は後で保存できます。
Ben Blank

17
@ IgnacioVazquez-Abrams long3.0で唯一の整数型ですが、名前が付けられていintます。(そして、古いものintはなくなっています。)
マイケル・ミオール2013年

70

Pythonは自然に任意の大きな整数をサポートします

例:

>>>10 ** 1000 100000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000

たとえば、巨大な整数値fib(4000000)を取得することもできます。

しかし、それでも(現時点では)任意の大きなフロートをサポートしていませ !!

大きくて大きいフロートが必要な場合は、decimalモジュールで確認してください。これらのforunsでの使用例があります:OverflowError:(34、 'Result too large')

別のリファレンス:http : //docs.python.org/2/library/decimal.html

スピードアップが必要な場合はgmpyモジュールを使用することもできます(これはおそらく興味があるでしょう):コードで大きな数値を処理する

別のリファレンス:https : //code.google.com/p/gmpy/


32

面白くするためにこれを行うこともできますが、それ以外はお勧めできません。それは私が考えることができる何もスピードアップしないでしょう。

  • カードを手に入れることは、配列にアクセスするよりもはるかに高価な整数因数分解操作になります。

  • カードを追加することは乗算であり、カード除算を削除することは、どちらも大きなマルチワード数であり、リストから要素を追加または削除するよりもコストのかかる操作です。

  • 手の実際の数値は何も教えてくれません。プライムを因数分解し、ポーカールールに従って2つのハンドを比較する必要があります。そのようなハンドのh1 <h2は何も意味しません。


25

Pythonは自然に任意の大きな整数をサポートします:

In [1]: 59**3*61**4*2*3*5*7*3*5*7
Out[1]: 62702371781194950
In [2]: _ % 61**4
Out[2]: 0

3

pythonインタプリタがそれを処理します。操作(+、-、*、/)を実行するだけで、通常どおり機能します。

int値は無制限です。

除算を行う場合は注意してください。デフォルトでは、商はに変換されますが、そのような大きな数はサポートされてfloatfloatません。このfloatような大きな数値をサポートしていないというエラーメッセージが表示されるfloat場合は、商が大きすぎて格納できないことを意味します//。床除算()を使用する必要があります。

小数点以下の小数点は無視されるintため、結果はになるため、多数の結果を得ることができます。

10//3 アウトプット 3

10//4 出力 2


1
あなたの回答は、質問の多数の問題にどのように対処しますか?
StupidWolf

つまり、通常の操作は多数実行できますが、除算には注意してください
Hedy
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.