2

この方法を使用して素数のリストを生成しようとしています。2 ... nごとにループして、2...nの倍数をチェックする必要があります。何らかの理由で、間違ったリストが変更されているようです。

import sys
import argparse
import math

parser = argparse.ArgumentParser(description='find the largest prime factor of a number')
parser.add_argument('n', type=int, help='number')
args = parser.parse_args()

sieve = []
for i in range(2,args.n+1): sieve.append(i) # tried int(i)


copy1 = sieve # tried making extra copies. . .
copy2 = sieve
copy3 = sieve
#print int(math.sqrt(args.n))

for index, i in enumerate(copy1):
    #print index, i
    for ii in copy2:
        #print ii
        if i % ii == 0:
            sieve[index]= None


print sieve

次のエラーが発生します。

Traceback (most recent call last):  
  File "3.py", line 22, in <module>
    if i % ii == 0: TypeError: unsupported operand type(s) for %:
'int' and 'str'
4

5 に答える 5

7

あなたはコピーを作っていません。参照を使用しているためcopy1copy2、 、およびcopy3すべてが同じリストを参照しています -- sieve。コピーする場合は、次を使用します。

copy1 = sieve[:]

のコピーを作成し、sieveに割り当てcopy1ます。

于 2010-12-02T16:13:39.633 に答える
2

使用する必要があります

copy1 = sieve[:] # tried making extra copies. . .
copy2 = sieve[:]
copy3 = sieve[:]

実際にリストをコピーします。それ以外の場合は、リストへの参照をコピーするだけです。

>>> a = [1,2]
>>> b = a
>>> c = a[:]
>>> b[0] = 0
>>> c[0] = 3
>>> a
[0, 2]
>>> b
[0, 2]
>>> c
[3, 2]
于 2010-12-02T16:14:27.513 に答える
2
copy1 = sieve
copy2 = sieve
copy3 = sieve

これらは参照用のコピーではありません。

primes = [2,3,5,7]

def is_prime(n):
    if n in primes:
        return True
    for item in primes:
        if n % item == 0:
            return False
    return True

assert is_prime(4) == False
assert is_prime(29) == True
assert is_prime(65) == False

良いふるい方法です

楽しいので単体テストを追加

true_primes = [int(item) for item in '11,13,17,19,23,29,31,37,41,43,47'.split(',')]
for item in xrange(10, 50):
    if is_prime(item) == True:
        assert item in true_primes
    else:
        assert item not in true_primes
于 2010-12-02T16:17:32.157 に答える
2

Python には参照セマンティクスがあります。一般に、a = b名前aが現在参照している値と同じ値を参照するようにbします。新しい値を作成または保存しません。

言及された [:] トリックを使用してリストを複製できます。物事をコピーするためのより一般的な解決策は、copyモジュールを使用することです。

ただし、通常、優れた Python コードでは、頻繁に明示的にコピーする必要はありません。リスト内包表記を使用して、既存のシーケンスの「変更されたバージョン」を作成することに慣れる必要があります。たとえば、ふるいを次のように実装できます (他にもいくつかのことを紹介します)。

import sys, argparse, math, itertools

parser = argparse.ArgumentParser(description='find the largest prime factor of a number')
parser.add_argument('n', type=int, help='number')
args = parser.parse_args()

# Using a loop over a 'range' to fill a list with increasing values is silly, because
# the range *is* a list of increasing values - that's how the 'for i in ...' bit works.
sieve = range(2, args.n + 1)

# We don't need to remember the original loop at all.
# Instead, we rely on each iteration of the sieve putting a new prime at the beginning.
for index in itertools.count(): # Counting upward,
  if index >= len(sieve): break # until we run out of elements,
  prime = sieve[index] # we grab the next prime from the list,
  sieve = [x for x in sieve if x == prime or x % prime != 0] # and sieve the list with it.
# Of course, we can optimize that by checking that prime < sqrt(args.n), or whatever.

print sieve
于 2010-12-02T16:32:19.563 に答える
1

Python 3.2 (Python 3.2 の新機能) のコピーを持っていないため、これをテストできませんでしたが、次のargparse2 つの明らかな点が思い浮かびます。

まず、する必要がありますsieve.append(int(i))

次に、sieve のコピーを作成しているのではなく、同じリストへの新しい参照を作成しているだけです。コピーを作成するには、

copy1 = sieve[:]
于 2010-12-02T16:19:30.587 に答える