在 Python 中处理非常大的数字
我一直在考虑用 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]
这将为每手牌提供一个数值,通过模数可以告诉我手中有多少个国王或有多少颗红心。 例如,任何拥有 5 个或更多梅花的手牌都会除以 2^5; 任何有 4 个 K 的手牌都会被 59^4 平分,等等。
问题是,像 AcAdAhAsKdKhKs 这样的七张牌手牌的哈希值约为 62.7 千万亿,这将需要远远超过 32 位的内部表示。 有没有一种方法可以在 Python 中存储如此大的数字,以便我对其执行算术运算?
I've been considering fast poker hand evaluation in Python. It occurred to me that one way to speed the process up would be to represent all the card faces and suits as prime numbers and multiply them together to represent the hands. To whit:
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]
AND
def HashVal(self):
return PokerCard.facePrimes[self.cardFace] * PokerCard.suitPrimes[self.cardSuit]
This would give each hand a numeric value that, through modulo could tell me how many kings are in the hand or how many hearts. For example, any hand with five or more clubs in it would divide evenly by 2^5; any hand with four kings would divide evenly by 59^4, etc.
The problem is that a seven-card hand like AcAdAhAsKdKhKs has a hash value of approximately 62.7 quadrillion, which would take considerably more than 32 bits to represent internally. Is there a way to store such large numbers in Python that will allow me to perform arithmetic operations on it?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
Python 支持“bignum”整数类型,可以处理任意大的数字。 在Python 2.5+中,这种类型称为
long
,与int
类型分开,但解释器会自动使用更合适的类型。 在 Python 3.0+ 中,int
类型已被完全删除。不过,这只是一个实现细节 - 只要您有 2.5 或更高版本,只需执行标准数学运算,任何超出 32 位数学边界的数字都将自动(且透明地)转换为 bignum。
您可以在 PEP 0237 中找到所有血腥细节。
Python supports a "bignum" integer type which can work with arbitrarily large numbers. In Python 2.5+, this type is called
long
and is separate from theint
type, but the interpreter will automatically use whichever is more appropriate. In Python 3.0+, theint
type has been dropped completely.That's just an implementation detail, though — as long as you have version 2.5 or better, just perform standard math operations and any number which exceeds the boundaries of 32-bit math will be automatically (and transparently) converted to a bignum.
You can find all the gory details in PEP 0237.
Python 自然支持任意大整数:
示例:
例如,您甚至可以获得一个巨大的整数值,纤维蛋白(4000000)。
但它仍然不(目前)支持任意大的浮动!
如果您需要一个很大的浮点数,请检查小数模块。 此网站上有使用示例:OverflowError: (34, '结果太大' )
另一个参考:9.4。 十进制 - 十进制定点和浮点算术
如果您需要加速(这可能是您感兴趣的),您甚至可以使用 gmpy 模块:在代码中处理大数字
另一个参考:gmpy (Google 代码。
Python supports arbitrarily large integers naturally:
Example:
You could even get, for example, a huge integer value, fib(4000000).
But still it does not (for now) supports an arbitrarily large float!!
If you need one big, large, float then check up on the decimal Module. There are examples of use on this site: OverflowError: (34, 'Result too large')
Another reference: 9.4. decimal — Decimal fixed point and floating point arithmetic
You can even using the gmpy module if you need a speed-up (which is likely to be of your interest): Handling big numbers in code
Another reference: gmpy (Google Code. Read-only)
你可以为了好玩而这样做,但除此之外,这不是一个好主意。 它不会加速我能想到的任何事情。
获取手中的牌将是一个整数因式分解操作,这比仅仅访问数组要昂贵得多。
获取手中的牌
添加卡片将是乘法,删除卡片除法,两者都是大型多字数字,这比在列表中添加或删除元素更昂贵的操作。
一手牌的实际数值不会告诉你任何信息。 您需要分解质数并遵循扑克规则来比较两手牌。 h1 < 对于这样的牌,h2 没有任何意义。
You could do this for the fun of it, but other than that it's not a good idea. It would not speed up anything I can think of.
Getting the cards in a hand will be an integer factoring operation which is much more expensive than just accessing an array.
Adding cards would be multiplication, and removing cards division, both of large multi-word numbers, which are more expensive operations than adding or removing elements from lists.
The actual numeric value of a hand will tell you nothing. You will need to factor the primes and follow the Poker rules to compare two hands. h1 < h2 for such hands means nothing.
Python 自然支持任意大的整数:
Python supports arbitrarily large integers naturally:
Python 解释器将为您处理它。 您只需执行您的操作(+、-、*、/),它就会正常工作。
int
值是无限的。做除法时要小心。 默认情况下,商会转换为
float
,但float
不支持这么大的数字。 如果您收到一条错误消息,指出float
不支持如此大的数字,则意味着商太大而无法存储在float
中,您必须使用下限除法(<代码>//)。它会忽略小数点后面的任何小数,这样,结果将是
int
,因此您可以获得大数结果。The Python interpreter will handle it for you. You just have to do your operations (+, -, *, /), and it will work as normal.
The
int
value is unlimited.Be careful when doing division. By default, the quotient is turned into
float
, butfloat
does not support such large numbers. If you get an error message sayingfloat
does not support such large numbers, then it means the quotient is too large to be stored infloat
you’ll have to use floor division (//
).It ignores any decimal that comes after the decimal point, this way, the result will be
int
, so you can have a large number result.为什么你想要这样做? 如果您坚持将手存储为单个编码值而不是字典或列表,请使用位字符串而不是素数的乘积。 乘法和素数分解很慢。
将每张卡编码为 2 的幂(1、2、4、8、16 等)。 您可以使用
hand |= card
添加一张牌。 您可以使用if hand & 检查一张牌。 卡> 0 。
Why would you ever want to do this? If you insist on storing the hand as a single encoded value instead of a dict or list use a bit-string instead of the product of primes. Multiplication and prime number factorization is slow.
Encode each card as a power of 2 (1, 2, 4, 8, 16, etc.). You can add a card with
hand |= card
. You can check for a card withif hand & card > 0
.