范围太大Python

时间:2012-03-22 04:50:18

标签: python range

我试图找到数字x的最大素数因子,Python给出了范围太大的错误。我尝试过使用x range但是我遇到了OverflowError:Python int太大而无法转换为C long

x = 600851475143
maxPrime = 0


for i in range(x):
    isItPrime = True
    if (x%i == 0):
        for prime in range(2,i-1):
            if (i%prime == 0):
                isItPrime = False
        if (isItPrime == True):

            if (i > maxPrime):
                maxPrime = i;

print maxPrime

6 个答案:

答案 0 :(得分:28)

在旧的(2.x)版本的Python中,xrange只能处理Python 2.x int,它们受本机长整数大小的约束你的平台。另外,range预先在Python 2.x上分配一个包含所有数字的列表,因此不适用于大型参数。

您可以切换到3.x(推荐),或者long int(在C中)为64位长的平台,或者使用以下插件:

import itertools
range = lambda stop: iter(itertools.count().next, stop)

同样地,以简单的形式:

def range(stop):
   i = 0
   while i < stop:
       yield i
       i += 1

答案 1 :(得分:6)

这就是我要做的事情:

def prime_factors(x):
    factors = []
    while x % 2 == 0:
        factors.append(2)
        x /= 2
    i = 3
    while i * i <= x:
        while x % i == 0:
            x /= i
            factors.append(i)
        i += 2
    if x > 1:
        factors.append(x)
    return factors

>>> prime_factors(600851475143)
[71, 839, 1471, 6857]

这很快,我认为是对的。采用所发现因素的最大值非常简单。


2017年11月8日

回到这5年之后,我会使用yieldyield from以及在主要范围内更快地计算:

def prime_factors(x):
    def diver(x, i):
        j = 0
        while x % i == 0:
            x //= i
            j += 1
        return x, [i] * j
    for i in [2, 3]:
        x, vals = diver(x, i)
        yield from vals
    i = 5
    d = {5: 2, 1: 4}
    while i * i <= x:
        x, vals = diver(x, i)
        yield from vals
        i += d[i % 6]
    if x > 1:
        yield x

list(prime_factors(600851475143))

dict {5: 2, 1: 4}使用的事实是你不必查看所有奇数。高于3,所有数字x % 6 == 3都是3的倍数,因此您只需要查看x % 6 == 1x % 6 == 5,您可以通过交替添加2和4来跳转到这些数字,从5开始

答案 2 :(得分:4)

接受的答案表明xrange的替代品,但仅涵盖一个案例。这是一个更普遍的替代品。

def custom_range(start=0,stop=None,step=1):
    '''xrange in python 2.7 fails on numbers larger than C longs.
    we write a custom version'''
    if stop is None:
        #handle single argument case. ugly...
        stop = start
        start = 0
    i = start
    while i < stop:
        yield i
        i += step

xrange=custom_range

答案 3 :(得分:1)

我肯定会坚持使用xrange,因为创建一个介于0之间的列表,看起来像无穷大的数字会对内存造成负担。 xrange只会在被问到时生成数字。对于数量太大的问题,您可能想尝试“长”。这可以通过在数字的末尾写一个L来实现。我制作了自己的版本来测试它。我进行了一次小睡眠,以免将我的计算机破坏成几乎while(1)的循环。我也不耐烦地看到程序完全结束,所以我输入了打印语句

from time import sleep

x = 600851475143L
maxPrime = 0

for i in xrange(1,x):
    isItPrime = True
    if (x%i) == 0:
        for prime in xrange(2,i-1):
            if (i%prime) == 0:
                isItPrime = False
                break
        if isItPrime:
            maxPrime = i
            print "Found a prime: "+str(i)
    sleep(0.0000001)


print maxPrime

希望这有帮助!

编辑: 我还做了一些编辑以产生这个版本。这是相当有效的,我检查了这个程序提供的相当多的数字(它似乎到目前为止检查):

from time import sleep

x = 600851475143L

primes = []

for i in xrange(2,x):
    isItPrime = True
    for prime in primes:
        if (i%prime) == 0:
            isItPrime = False
            break
    if isItPrime:
        primes.append(i)
        print "Found a prime: "+str(i)
    sleep(0.0000001)


print primes[-1]

答案 4 :(得分:0)

非常有用的代码,这不是获取分隔符的最佳方式,我已经使用forrange完成了它,但我无法执行它由于变量很长,所以我决定用一段时间来实现它,并自己增加一个计数器。

对于32位int,如13195:

# The prime factors of 13195 are 5, 7, 13 and 29.
# What is the largest prime factor of the number 600851475143 ?

i = 13195
for j in xrange(2, i, 1):
    if i%j == 0:
        i = i/j
        print j

更长的数字的好方法:

# The prime factors of 13195 are 5, 7, 13 and 29.
# What is the largest prime factor of the number 600851475143 ?

i = 600851475143
j = 2

while i >= j:
    if i%j == 0:
        i = i/j
        print j
    j = j+1

最后一个素数是最后一个打印值。

答案 5 :(得分:0)

python 2 range()的另一种实现方式:

import itertools
import operator

def range(*args):
    """Replace range() builtin with an iterator version."""
    if len(args) == 0:
        raise TypeError('range() expected 1 arguments, got 0')
    start, stop, step = 0, args[0], 1
    if len(args) == 2: start, stop = args
    if len(args) == 3: start, stop, step = args
    if step == 0:
        raise ValueError('range() arg 3 must not be zero')
    iters = itertools.count(start, step)
    pred = operator.__ge__ if step > 0 else operator.__le__
    for n in iters:
        if pred(n, stop): break
        yield n