цикл по числам и оценить, делятся ли числа на определенные числа - PullRequest
0 голосов
/ 30 октября 2018

Я написал программу для оценки того, какие числа в определенном диапазоне делятся только на определенные числа (в диапазоне от 1 до 9). Пока что код работает, но я протестировал шаги, которые он выполняет, в pythontutor http://www.pythontutor.com/visualize.html#mode=edit и что-то странное произошло.

Во втором цикле код не всегда проверяет все значения (k) на его делимость, но иногда пропускает последнее значение (k). Лучше привести пример:

Liste = []
for i in range (1500, 1700):
    if i%5 == 0 and i%7 == 0:
        Liste.append(i)
print (Liste)

Teiler = [2, 3, 4, 6, 8, 9]
for k in Liste:
    z = 0
    for w in range (len(Teiler)):
        if k%Teiler[z] == 0:
            Liste.remove(k)
            z += 1
            break
        else:
            z += 1

print (Liste)

Здесь вывод выглядит следующим образом:

[1505, 1540, 1575, 1610, 1645, 1680]

[1505, 1575, 1645]

И это вывод, который должен быть, как и во втором списке, это только числа, делимые на 5 и 7. Также на pythontutor второй цикл for проходит все значения (k).

Но когда я изменяю диапазон числа следующим образом (строка 2, изменяю диапазон с 1700 на 1800):

Liste = []
for i in range (1500, 1800):
    if i%5 == 0 and i%7 == 0:
        Liste.append(i)
print (Liste)

Teiler = [2, 3, 4, 6, 8, 9]
for k in Liste:
    z = 0
    for w in range (len(Teiler)):
        if k%Teiler[z] == 0:
            Liste.remove(k)
            z += 1
            break
        else:
            z += 1

print (Liste)

вывод выглядит следующим образом:

[1505, 1540, 1575, 1610, 1645, 1680, 1715, 1750, 1785]

[1505, 1575, 1645, 1715, 1785]

Если я запускаю этот код на pythontutor, код останавливается на k = 1750 и не проверяет k = 1785.

Почему так себя ведет? Это проблема с проверкой на pythontutor? Или есть проблема с моим кодом?

Я хочу понять, почему Python делает то, что делает.

Большое спасибо за вашу помощь. Мне жаль, если это вопрос нуба или я упускаю что-то очевидное.

Ответы [ 2 ]

0 голосов
/ 30 октября 2018

Не удаляйте элементы из списка, по которому вы перебираете, как говорится в другом ответе. Изменение длины списка влияет на итерацию. Пример:

>>> L=list(range(10))
>>> for i in L:
...   if i==5: L.remove(i)
...   print(i)
...
0
1
2
3
4
5  # removed 5, and skipped 6!
7
8
9

Также w никогда не используется, хотя z является эквивалентом. Вместо этого, выполните итерацию непосредственно над Teiler и добавьте элементы в новый список, если он удовлетворяет вашему условию:

Liste = []
for i in range (1500, 1800):
    if i%5 == 0 and i%7 == 0:
        Liste.append(i)
print (Liste)

Liste2 = []
Teiler = [2, 3, 4, 6, 8, 9]
for k in Liste:
    for w in Teiler:
        if k % w == 0:
            break
    else:
        Liste2.append(k)

print(Liste2)

Выход:

[1505, 1645, 1715]

Если вы не видели for/else, else выполняется только в том случае, если вы не выходите из цикла for, поэтому все значения k % w != 0 должны быть истинными.

Еще один вариант - использовать список пониманий , который действительно упрощает код:

L = [i for i in range(1500,1800) if i%5 == 0 and i%7 == 0]
L = [x for x in L if all(x % k != 0 for k in (2,3,4,6,8,9))]
print(L)

Выход:

[1505, 1645, 1715]

Примечание. 1575 и 1785 делятся на 3, поэтому в обоих ваших выборочных списках были ошибки при удалении значений из списка.

0 голосов
/ 30 октября 2018

Ваша проблема в этой строке:

Liste.remove(k)

потому что вы удаляете элемент из того же списка, который вы используете для цикла for, поэтому при удалении элемента список будет короче, но на следующей итерации вы перейдете к элементу.

Я советую использовать два списка или использовать цикл while, и когда вы удаляете элемент из списка, вы не переходите к следующей итерации и уменьшаете длину списка 1; Пример:

Liste = []
for i in range (1500, 1800):
    if i%5 == 0 and i%7 == 0:
        Liste.append(i)
print (Liste)

Teiler = [2, 3, 4, 6, 8, 9]

l=len(Liste)
i=0
while i<l:
    k=Liste[i]
    z = 0
    for w in range (len(Teiler)):
        if k%Teiler[z] == 0:
            Liste.remove(k)
            l-=1
            i-=1
            z += 1
            break
        else:
            z += 1
    i+=1

Этот код может быть улучшен, но для того, чтобы вы поняли, как вы можете это сделать

...