Практическая задача по Python: все делители числа

Раздел: Образовательные материалы -> Обучение Python для школьников

Разбор задачи о делителях числа

Условие:

Пользователь вводит целое положительное число. Программа выводит все его делители (включая 1 и само число).

Как реализовать простой перебор делителей?

Самый очевидный способ - проверить все числа от 1 до n. Если n делится на i без остатка, то i - делитель.

n = int(input("Введите число: "))
for i in range(1, n + 1):
    if n % i == 0:
        print(i)

задания python 8 класс (задания по python для 8 класса)

Типичные ошибки:

  • Забывают преобразовать строку в число - возникает ошибка TypeError при попытке деления.
  • Используют range(1, n) вместо range(1, n+1) - тогда само число не выводится.

Как оптимизировать перебор, чтобы программа работала быстрее для больших чисел?

Достаточно проверять числа до квадратного корня из n. Если i - делитель, то парный делитель - n // i. Это сокращает количество итераций с n до √n.

import math
n = int(input("Введите число: "))
for i in range(1, int(math.isqrt(n)) + 1):
    if n % i == 0:
        print(i)
        if i != n // i:
            print(n // i)

Проблемы:

  • Делители выводятся не в порядке возрастания (сначала маленькие, потом большие). Для упорядоченного вывода нужно собрать их в список и отсортировать.
  • Ошибка при использовании math.sqrt вместо math.isqrt - результат может быть неточным для больших чисел (потеря точности из-за float). math.isqrt гарантирует целое число.

Как записать решение в одну строку с помощью list comprehension?

Список делителей можно создать выражением [i for i in range(1, n+1) if n % i == 0]. Это компактно, но не оптимизировано.

n = int(input("Введите число: "))
divisors = [i for i in range(1, n+1) if n % i == 0]
print("Делители:", divisors)

Для квадратичной оптимизации с tuple comprehension не получится, так как нужно добавлять оба делителя.

Как оформить поиск делителей в виде функции для многократного использования?

Функция принимает число и возвращает список делителей. Удобно для дальнейшего использования в других программах.

def get_divisors(n):
    """Возвращает список всех делителей числа n"""
    divisors = []
    for i in range(1, int(n**0.5) + 1):
        if n % i == 0:
            divisors.append(i)
            if i != n // i:
                divisors.append(n // i)
    return sorted(divisors)

n = int(input("Число: "))
print("Делители:", get_divisors(n))

Распространённые ошибки:

  • Не используют sorted() - результат будет неупорядоченным.
  • Путают порядок добавления: сначала парный делитель, потом основной - теряется симметрия.

Как обработать ввод некорректных данных (не число, отрицательное число)?

Использовать конструкцию try-except для перехвата ValueError при преобразовании в int. Для отрицательных чисел задача не имеет смысла - можно потребовать повторный ввод.

while True:
    try:
        n = int(input("Введите положительное целое число: "))
        if n > 0:
            break
        else:
            print("Число должно быть положительным.")
    except ValueError:
        print("Ошибка: введите целое число.")

# Далее поиск делителей

Типичная ошибка:

  • Забывают про бесконечный цикл - если пользователь вводит неверные данные, программа не завершается. Это правильно, но нужно предусмотреть выход по пустому вводу или команде 'exit'.

Расширенные примеры по теме делителей числа

Пример 1: Нахождение суммы делителей

Пример
def sum_divisors(n):
    total = 0
    for i in range(1, int(n**0.5) + 1):
        if n % i == 0:
            total += i
            if i != n // i:
                total += n // i
    return total

print(sum_divisors(12))  # 1+2+3+4+6+12 = 28
28

Пример 2: Проверка, является ли число совершенным (сумма делителей равна числу)

Пример
def is_perfect(n):
    if n <= 1:
        return False
    return sum_divisors(n) == n

for num in range(1, 10001):
    if is_perfect(num):
        print(num, end=' ')
# 6, 28, 496, 8128
6 28 496 8128

Пример 3: Вывод всех простых чисел до заданного предела с помощью решета Эратосфена

Пример
def sieve_of_eratosthenes(limit):
    is_prime = [True] * (limit + 1)
    is_prime[0] = is_prime[1] = False
    for i in range(2, int(limit**0.5) + 1):
        if is_prime[i]:
            for j in range(i*i, limit + 1, i):
                is_prime[j] = False
    return [num for num, prime in enumerate(is_prime) if prime]

print(sieve_of_eratosthenes(30))
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]

Пример 4: Подсчёт количества делителей с использованием разложения на простые множители

Пример
from collections import Counter

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

def count_divisors(n):
    factors = prime_factors(n)
    counter = Counter(factors)
    count = 1
    for exp in counter.values():
        count *= (exp + 1)
    return count

print(count_divisors(144))  # 144 = 2^4 * 3^2 -> (4+1)*(2+1)=15
15

Пример 5: Использование math.isqrt для точного квадратного корня (Python 3.8+)

Пример
import math
n = 1000000
sqrt_n = math.isqrt(n)
print(sqrt_n)  # 1000
# Сравнение с math.sqrt: int(math.sqrt(n)) может дать 999 из-за округления
1000

Пример 6: Генерация всех делителей с помощью рекурсии (экзотический способ)

Пример
def all_divisors_rec(n, i=1):
    if i > n:
        return []
    if n % i == 0:
        return [i] + all_divisors_rec(n, i+1)
    else:
        return all_divisors_rec(n, i+1)

print(all_divisors_rec(18))  # [1, 2, 3, 6, 9, 18]
[1, 2, 3, 6, 9, 18]

Пример 7: Поиск наибольшего общего делителя (НОД) через алгоритм Евклида - обратная задача

Пример
def gcd(a, b):
    while b:
        a, b = b, a % b
    return a

print(gcd(48, 18))  # 6
6

Задания по Python для 8 класса - comments

En
задания python 8 класс (python)