#python #python-3.x #math #greatest-common-divisor
#python #python-3.x #математика #наибольший общий делитель
Вопрос:
Я пытаюсь написать код, который дает вам числа, которые меньше заданного или введенного числа, а их GCD равен 1 . Я написал этот код, но я не знаю, работает ли он или почему нет. Например, я выбрал номер 6. массив будет выглядеть как [1,2,3,4,5] . И я хочу отфильтровать числа, для которых GCD равно 1. Так что это будет [1,5] . И их количество равно двум.
a
это номер ввода и b
номера списка, которые меньше введенной единицы и не равны нулю. А затем распечатайте его.
a = int(input("enter number n"))
b = list(range(1,a))
print (b)
Затем я преобразую список в массив
for i in range(1, len(b)):
b[i] = int(b[i])
и затем это
r = a % b[i]
q = int ( a / b[i])
while(r!=0):
a = b[i]
b[i] = r
q = int ( a / b[i])
r = a - (b[i] * q)
print ( a , b[i], r )
break
Я новичок.
Комментарии:
1. Как вы не знаете, работает ли это. Вы тестировали его на некоторых входных данных и дали ли они ожидаемые результаты?
2. Да, я протестировал это, и я думаю, что не получил результатов, которые хотел, поэтому разместил здесь.
3.
for i in range(1, len(b)): b[i] = int(b[i])
неверно по двум причинам. 1) Это не имеет никакого эффекта, так какb
это уже список целых чисел. 2) Списки проиндексированы на 0, поэтому правильными итерациями для каждого элементаb
будетfor i in range(0, len(b)):
или простоfor i in range(len(b)):
4. «Так что это будет [1,5]». — Я не вижу никакой связи между этим ожидаемым результатом и описанием, которое предшествует ему.
5. Как я уже упоминал, я новичок, поэтому, возможно, я делаю что-то не так. Мне было интересно, может ли этот код мне помочь, я пытаюсь написать теорему Эйлера.
Ответ №1:
Несколько комментариев о вашем коде:
- Вы всегда должны инкапсулировать подобный код в функцию; напишите функцию
find_coprimes
, которая принимает аргументn
и возвращает нужный вам список; - Чтобы проверить правильность вашей функции, напишите ссылочную функцию
find_coprimes_ref
, которая выполняет то же самое, но использует библиотечные функции, чтобы убедиться в отсутствии ошибок; это научит вас искать соответствующие библиотечные функции, и вы сможете сравнить результаты двух функций; - Начальный цикл
for i in range(1, len(b)): b[i] = int(b[i])
неверен по двум причинам; 1) Он не имеет никакого эффекта, посколькуb
уже является списком целых чисел. 2) Списки проиндексированы на 0, поэтому правильными итерациями для каждого элементаb
будетfor i in range(0, len(b)):
или простоfor i in range(len(b)):
; - В вашем коде есть два вложенных цикла: цикл
while
-loop, выполняемый многократно внутри циклаfor
-loop; всякий раз, когда есть такие вложенные циклы, вы должны убедиться, что переменные повторно инициализируются так, как вы предполагаете, в начале внешнего цикла; в вашем случае переменнаяa
изменяется внутри циклаwhile
-loop, ив результате его значение неверно в начале следующей итерацииfor
цикла. break
Оператор в конце циклаwhile
-loop не имеет смысла; в общем,break
операторы имеют смысл, только если они инкапсулированы вif
условное выражение и действуют как замена условия цикла; но всегда можно писать циклы без использованияbreak
вообще, и я рекомендую вамbreak
полностью забыть об этом.- После выполнения вычисления gcd с использованием
q
иr
в вашем коде отсутствует что-то, что указывает, следует ли сохранятьb[i]
или нет в конечном результате; - Для целочисленного деления в python лучше использовать
//
, а неint(... / ...)
.
Код
import math
def find_coprimes_ref(n):
return [x for x in range(1,n) if math.gcd(x,n) == 1]
def find_coprimes(n):
result = []
for x in range(1, n):
a = n
b = x
r = a % b
q = a // b
while (r > 1):
a = b
b = r
q = a // b
r = a - b * q
if (r == 1):
result.append(x)
return result
# TESTING
for n in range(1, 31):
coprimes_ref = find_coprimes_ref(n)
coprimes = find_coprimes(n)
if coprimes_ref != coprimes:
print(n, coprimes_ref, coprimes)
Обратите внимание, что мой код никогда не изменяется n
или x
не выполняется в цикле; вместо этого я вызываю копии a
b
и изменяю копии.
Инкапсуляция еще больше
Обратите внимание, насколько function find_coprimes_ref
намного легче читать, чем function find_coprimes
? Это не только потому, что мы использовали библиотечную функцию math.gcd
. Это потому, что библиотечная функция math.gcd
— это чисто инкапсулированная функция с именем, которое четко объясняет, что она делает. Ваш код содержит цикл while внутри цикла for, и немного сложно отслеживать каждую переменную и все, что происходит, и не терять из виду нашу подзадачу и общую цель.
Чтобы вашу функцию было легче читать, легче кодировать и легче отлаживать, вы должны инкапсулировать вычисление gcd внутри вызываемой функции gcd
:
def gcd(a, b):
r = a % b
q = a // b
while (r > 1):
a = b
b = r
q = a // b
r = a - b * q
return r
def find_coprimes(n):
result = []
for x in range(1, n):
if gcd(a, b) == 1:
result.append(x)
return result
# TESTING GCD
for b in range(1, 31):
for a in range(b, 31):
r1 = math.gcd(a, b)
r2 = gcd(a, b)
if r1 != r2:
print(a, b, r1, r2)
# TESTING FIND_COPRIMES
for n in range(1, 31):
coprimes_ref = find_coprimes_ref(n)
coprimes = find_coprimes(n)
if coprimes_ref != coprimes:
print(n, coprimes_ref, coprimes)
Есть две причины, по которым код теперь легче отлаживать:
- Логика for
gcd
и forfind_coprimes
четко разделена, что означает, что вы можетеgcd
четко рассуждать без какого-либо риска испортить список и другие переменные, используемые вfind_coprimes
; - Вы можете протестировать отдельно свою функцию
gcd
и свою функциюfind_coprimes
; и если что-то не работает правильно, вы будете более точно знать, где искать проблему, а не просто думать: «Ну, что-то не так где-то в коде, но я понятия не имею, где».
Комментарии:
1. Обратите внимание, что существует встроенная
divmod
функция, поэтому вы можете заменитьq = a // b; r = a - b * q
наq, r = divmod(a, b)
. Если вам просто нужен остаток, есть оператор modulo :r = a % b
.
Ответ №2:
В вашем коде есть несколько ошибок, например, break
внутри цикла while. Я переработал ваш код, а также добавил встроенную math.gcd
функцию для сравнения результатов.
import math
def math_inbuilt_gcd(a, b):
gcd_one = []
for x in b:
if math.gcd(x, a) == 1:
gcd_one.append(x)
print("gcd_one_math_fun:", gcd_one)
def gcd_my_fun(a, b):
gcd_arr = []
for i in range(len(b)):
x, y = a, b[i] # taking x, y just to make things clear
r = x % y # remainder
q = int(x / y) # quotient
while(r != 0):
x = y
y = r
q = int(x/y)
r = x % y
if y == 1:
gcd_arr.append(b[i])
print("gcd_one_my_fun:", gcd_arr)
a = int(input("Enter number: "))
b = list(range(1, a))
print("b:", b)
math_inbuilt_gcd(a, b)
gcd_my_fun(a, b)
Вывод:
Enter number: 10
b: [1, 2, 3, 4, 5, 6, 7, 8, 9]
gcd_one_math_fun: [1, 3, 7, 9]
gcd_one_my_fun: [1, 3, 7, 9]