数値xの最大の素数を見つけようとしています、Pythonは、範囲が大きすぎるというエラーを表示します。x範囲を使用しようとしましたが、OverflowErrorが発生します:= Python intが大きすぎてClongに変換できません
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
古い(2.x)バージョンのPythonでは、xrange
はネイティブによってバインドされているPython 2.x int
sのみを処理できますlong integerプラットフォームのサイズ。さらに、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
これは私がすることです:
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-08
5年後にこれに戻ると、私はyield
とyield 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 == 1
とx % 6 == 5
のみを確認する必要があり、5から始めて2と4を交互に加算することで、これらの間を移動できます。 。
受け入れられた回答は、xrangeのドロップイン置換を示唆していますが、カバーするのは1つのケースのみです。これは、より一般的なドロップインの代替品です。
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
0から無限大に匹敵する数のように見えるリストを作成すると、メモリに負担がかかるため、私は間違いなくxrangeに固執します。 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]
非常に非効率的なコード。これは分周器を取得するための最良の方法ではありません。for
とrange
を使用して実行しましたが、変数が長いため実行できないため、決定しました。しばらく使用するためにそれを実装し、自分でカウンターをインクリメントします。
13195のような32ビットint
の場合:
# 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
最後の素数は、最後に出力された値です。
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