Обробка дуже великої кількості в Python


140

Я розглядав питання швидкої оцінки покеру в Python. Мені прийшло в голову, що одним із способів прискорити процес буде представити всі обличчя та костюми карт як прості числа та помножити їх разом, щоб представити руки. Побілити:

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]

Це дало б кожній руці числове значення, яке через модуль могло б сказати мені, скільки царів у руці або скільки сердець. Наприклад, будь-яка рука з п'ятьма і більше клубами ділиться рівномірно на 2 ^ 5; будь-яка рука з чотирма королями поділила б рівномірно 59 ^ 4 і т.д.

Проблема полягає в тому, що рука із семи картами, як AcAdAhAsKdKhKs, має значення хеш-орієнтовно 62,7 квадратних мільйонів, що би потребувало значно більше 32 біт для внутрішньої репрезентації. Чи є спосіб зберігати такі великі числа в Python, який дозволить мені виконувати арифметичні операції на ньому?


13
Ви впевнені, що як тільки ви почнете представляти свої дані таким чином, ви все одно побачите суттєве покращення швидкості? Я усвідомлюю, що це не відповідає на ваші запитання, але все ж ..
Томі

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

Відповіді:


177

Python підтримує цілий тип "bignum", який може працювати з довільно великими числами. У Python 2.5+ цей тип називається longі відокремлений від intтипу, але перекладач автоматично використовуватиме те, що є більш підходящим. У Python 3.0+ intтип видалено повністю.

Це лише детальна інформація про впровадження - якщо у вас версія 2.5 або вище, просто виконайте стандартні математичні операції, і будь-яке число, яке перевищує межі 32-бітової математики, буде автоматично (і прозоро) перетворене в бінду.

Ви можете знайти всі деталі горі в PEP 0237 .


2
Питання полягає в тому, чи перевищує ефективність використання bignum замість 32-бітових цілих чисел перевагу продуктивності від розумного методу оцінки руки, який він використовує.
Chris Upchurch

3
Власне, бар'єр між int та long був зламаний у 2,5. 3.0 повністю видаляє int, що робить довгим єдиний цілий тип.
Ігнасіо Васкес-Абрамс

1
Наскільки велика велика кількість? Чи може це бути PHI ^ 4000000?
Майк Карон

9
@Mike Caron - Якщо структура, вказана в PEP 0237, точна, longдовжини s (у цифрах) зберігаються як непідписані 32-бітні цілі числа, до 4,294,967,295 цифр, тобто вони можуть легко вмістити φ ** (4 * 10 ** 6 ), що становить "лише" 832 951 цифру. Однак φ не є цілим числом, тому для обчислення числа вам потрібно буде використовувати десятковий (бітум з плаваючою комою Python). longОднак ви можете зберегти результат згодом.
Бен Бланк

17
@ IgnacioVazquez-Abrams Просто уточнення, long - це єдиний цілий тип у 3.0, але він названий int. (І старого intвже немає.)
Майкл Міор

70

python природно підтримує довільно великі цілі числа :

приклад:

>>>10 ** 1000 100000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

Можна навіть отримати, наприклад, величезне ціле значення, fib (4000000).

Але все - таки це робить НЕ (на даний момент) підтримує як завгодно великий поплавок !!

Якщо вам потрібен один великий, великий, плаваючий, то перевірити на десятковий модуль. Наведено приклади використання цих фортун: OverflowError: (34, "Результат занадто великий")

Ще одна довідка: http://docs.python.org/2/library/decimal.html

Ви навіть можете використовувати модуль gmpy, якщо вам потрібна швидкість (яка, ймовірно, зацікавить вас): Обробка великих номерів у коді

Ще одна довідка: https://code.google.com/p/gmpy/


33

Ви можете це зробити для задоволення, але крім того, що це не гарна ідея. Це не прискорило б нічого, що я можу придумати.

  • Отримання карт в руки буде цілою операцією факторингу, яка набагато дорожче, ніж просто доступ до масиву.

  • Додавання карток було б множенням та видаленням ділення карт, обох великих багатословних чисел, що є більш дорогими операціями, ніж додавання або видалення елементів зі списків.

  • Дійсне числове значення руки нічого не скаже. Вам потрібно буде розбити коефіцієнти і виконувати правила покеру, щоб порівняти дві руки. 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Значення не обмежена.

Обережно при виконанні поділу, за замовчуванням коефіцієнт перетворюється на float, але floatне підтримує таких великих чисел. Якщо ви отримаєте повідомлення про помилку, яке говорить про те, floatщо не підтримує настільки велику кількість, то це означає, що коефіцієнт занадто великий, щоб зберігати floatйого, вам доведеться використовувати підрозділ ( //).

Він ігнорує будь-яку десяткову частину, що надходить після десяткової крапки, таким чином, результат буде int, тому ви можете мати велику кількість результатів.

10//3 Виходи 3

10//4 виходи 2


1
Як ваша відповідь стосується великої кількості питань у питанні?
StupidWolf

Це означає, що ви можете просто робити звичайні операції з великою кількістю, але будьте обережні з поділом
Хеді
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.