Python'da çok büyük sayıların ele alınması


140

Python'da hızlı poker el değerlendirmesi yapmayı düşünüyorum. İşlemi hızlandırmanın bir yolunun, tüm kart yüzlerini ve takımlarını asal sayılar olarak göstermek ve elleri temsil etmek için onları çoğaltmak olduğu bana geldi. Katlamak için:

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]

VE

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

Bu, her ele, modulo aracılığıyla bana elinde kaç kralın veya kaç kalbin olduğunu söyleyebilecek sayısal bir değer verecektir. Örneğin, içinde beş veya daha fazla kulüp bulunan her el eşit olarak 2 ^ 5'e bölünür; dört krallı her el eşit olarak 59 ^ 4, vb.

Sorun, AcAdAhAsKdKhKs gibi yedi kartlı bir elin, yaklaşık 62.7 katrilyon hash değerine sahip olması ve dahili olarak temsil edilmesi 32 bitten çok daha fazla zaman almasıdır. Python'da üzerinde aritmetik işlemler yapmamı sağlayacak kadar büyük sayılar depolamanın bir yolu var mı?


13
Verilerinizi bu şekilde temsil etmeye başladığınızda, yine de önemli bir hız artışı göreceğinizden emin misiniz? Bunun sorularınıza cevap vermediğinin farkındayım, ama yine de ..
Thomi

3
Bir önerim var: Kart değerleri ve temsiller için ayrı değişkenler kullanmak yerine sözlükler kullanmanızı öneririm. (Yüzler = {'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} ve takım elbise = {'c': 2, 'd': 3, ' h ': 5,' s ': 7}.)
JAB

Yanıtlar:


177

Python, keyfi olarak büyük sayılarla çalışabilen bir "bignum" tamsayı türünü destekler. Python 2.5+ sürümünde bu tür çağrılır longve türden ayrıdır int, ancak yorumlayıcı hangisi daha uygunsa otomatik olarak kullanır. Python 3.0 ve sonraki sürümlerinde inttür tamamen kaldırılmıştır.

Bu sadece bir uygulama detayı olsa da - sürüm 2.5 veya daha iyisine sahip olduğunuz sürece, sadece standart matematik işlemleri yapın ve 32 bit matematik sınırlarını aşan herhangi bir sayı otomatik olarak (ve şeffaf bir şekilde) bignuma dönüştürülecektir.

Tüm kanlı detayları PEP 0237'de bulabilirsiniz .


2
Soru, 32 bit tamsayılar yerine bignum kullanmanın isabet ettiği performansın, kullandığı akıllı el değerlendirme yönteminden elde edilen performans faydasını aşıyor mu?
Chris Upchurch

3
Aslında, int ve long arasındaki bariyer 2.5'te kırıldı. 3.0 int'i tamamen ortadan kaldırarak tek tamsayı tipini uzun yapar.
Ignacio Vazquez-Abrams

1
Büyük bir sayı ne kadar büyük? PHI ^ 4000000 olabilir mi?
Mike Caron

9
@Mike Caron - PEP 0237'de listelenen yapı doğruysa, longs uzunlukları (rakam olarak) 4.294.967.295 basamağa kadar imzasız 32 bit tamsayılar olarak saklanır, yani easily ** (4 * 10 ** 6) ), "yalnızca" 832,951 basamaktır. Bununla birlikte, an bir tamsayı değildir, bu nedenle sayıyı hesaplamak için bir Ondalık (Python'un kayan noktalı bignum) kullanmanız gerekir . longAncak sonucu daha sonra saklayabilirsiniz .
Ben Blank

17
@ IgnacioVazquez-Abrams Sadece bir açıklama noktası, long3.0'daki tek tamsayı türüdür, ancak adlandırılmıştır int. (Ve eski intgitti.)
Michael Mior

70

python doğal olarak keyfi olarak büyük tam sayıları destekler :

misal:

>>>10 ** 1000 100000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

Örneğin, büyük bir tamsayı değeri olan fib (4000000) bile elde edebilirsiniz.

Ama yine de öyle değil (şimdilik) bir keyfi büyük destekler şamandıra !!

Bir büyük, büyük, şamandıra ihtiyacınız varsa, ondalık Modülü kontrol edin. Bu forun'larda kullanım örnekleri vardır: OverflowError: (34, 'Sonuç çok büyük')

Başka bir referans: http://docs.python.org/2/library/decimal.html

Bir hızlandırmaya ihtiyacınız varsa gmpy modülünü bile kullanabilirsiniz (ilginizi çekmesi muhtemeldir): Koddaki büyük sayıları işleme

Başka bir referans: https://code.google.com/p/gmpy/


33

Bunu eğlenmek için yapabilirsiniz, ancak bunun dışında iyi bir fikir değil. Aklıma gelen hiçbir şeyi hızlandırmazdı.

  • Kartları elde tutmak, bir diziye erişmekten çok daha pahalı bir tamsayı faktoring işlemi olacaktır.

  • Kart eklemek, her ikisi de büyük çok kelimeli sayıların çoğaltılması ve kart bölümünün kaldırılması olacaktır;

  • Bir elin gerçek sayısal değeri size hiçbir şey söylemez. İki eli karşılaştırmak için asalleri hesaba katmanız ve Poker kurallarına uymanız gerekir. Bu tür eller için h1 <h2 hiçbir şey ifade etmez.


25

python doğal olarak keyfi olarak büyük tam sayıları destekler:

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 yorumlayıcısı sizin için halledecektir, sadece işlemlerinizi yapmalısınız (+, -, *, /) ve normal şekilde çalışacaktır.

intDeğeri sınırsızdır.

Bölme yaparken dikkatli olun, varsayılan olarak bölüm dönüştürülür float, ancak floatbu kadar büyük sayıları desteklemez. Bu floatkadar büyük sayıları desteklemediğini söyleyen bir hata mesajı alırsanız , bölümün saklanamayacak kadar büyük olduğu anlamına gelir, floatkat bölümü ( //) kullanmanız gerekir .

Ondalık noktadan sonra gelen ondalıkları yok sayar, bu şekilde sonuç olur int, böylece çok sayıda sonuç elde edebilirsiniz.

10//3 çıktılar 3

10//4 çıktılar 2


1
Cevabınız sorudaki büyük sayıları nasıl ele alıyor?
StupidWolf

Bu, normal işlemleri çok sayıda yapabileceğiniz, ancak bölünmeye dikkat edebileceğiniz anlamına gelir
Hedy
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.