在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
您确定一旦开始以这种方式表示数据,您仍然会看到速度上的显着提高吗?我意识到这不能回答您的问题,但是仍然..
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

Answers:


177

Python支持“ bignum”整数类型,该整数类型可以处理任意大数。在Python 2.5+中,将调用此类型long并将其与该int类型分开,但是解释器将自动使用更合适的那个类型。在Python 3.0+中,int类型已完全删除。

不过,这只是实现细节-只要您拥有2.5版或更高版本,就只需执行标准数学运算,并且任何超出32位数学界限的数字都将自动(透明地)转换为bignum。

您可以在PEP 0237中找到所有血腥细节。


2
问题是,使用bignum而不是32位整数对性能造成的影响是否超过了他所使用的聪明的手工评估方法所带来的性能收益。
克里斯·厄普彻奇

3
实际上,int和long之间的障碍已被打破2.5。3.0完全删除了int,使long成为唯一的整数类型。
伊格纳西奥·巴斯克斯

1
一个大数字有多大?可以是PHI ^ 4000000吗?
Mike Caron 2012年

9
@Mike Caron —如果PEP 0237中列出的结构是正确的,则longs的长度(以数字表示)存储为无符号32位整数,最多4,294,967,295位,这意味着它们可以轻松保存φ**(4 * 10 ** 6 ),即“仅” 832,951位数字。但是,φ不是整数,因此您需要使用Decimal(Python的浮点数)来计算数字。但是,您可以long随后存储结果。
本·布兰克

17
@ IgnacioVazquez-Abrams只是澄清一点,它long是3.0中唯一的整数类型,但它的名称为int。(而且旧int的不见了。)
Michael Mior

70

python 自然支持任意整数

例:

>>>10 ** 1000 100000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000百万000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

例如,您甚至可以得到一个巨大的整数值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

这意味着您可以进行大量的常规操作,但要小心划分
Hedy
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.