Разбор домашних заданий
- Более полные условия задач с подсказками доступны на uneex.org на странице самой задачи (посылке со страницы лекции)
Например, текст задачи 2 из прошлого Д/З открывается по ссылке
- Там же присутствуют т. н. «спойлеры» — изложение алгоритма для тех, кто устал думать. Чтобы почитать спойлер, надо выбрать в шапке страницы пункт «Комментарии»:
Разбор задач
К. О. как бы подсказывает нам, что вся задача сводится к вычислению логарифма по основанию 10.
Как сказано в пояснениях, если мы найдём два числа, одно чуть меньше правильного ответа, а другое — чуть больше, и разница между ними окажется достаточно маленькой, разница между любым их них и правильным ответом будет ещё меньше, и любой подойдёт в качестве решения.
Отформатируем спойлер, разбив его по действиям:
Для Y из диапазона 1/100…1000 x не может быть меньше -2 или больше 3. Начнем с x1=-2 и x2=3. Найдём середину этого диапазона, M = 0.5. Если 10**0.5<Y, значит ответ лежит в диапазоне от 0.5 до 3, а если 10**0.5⩾Y — в диапазоне от -2 до 0.5. Соответственно переназначим границы диапазона x1 и x2 и снова проверим новую середину M. Если 10**M<Y, ответ лежит между M и x2, а если 10**M⩾Y — между x1 и M. Будем повторять это последнее действие до тех пор, пока размер диапазона x2-x1 не окажется меньше 0.0000001.
Начнём переводить с русского на Python (с «# » начинаются т. н. комментарии, при виде которых Python игнорирует оставшийся конец строки. В комментарии можно писать что угодно!):
1 # Не забудем ввести Y
2 Y = float(input())
3
4 # Для Y из диапазона 1/100…1000 x не может быть меньше -2 или больше 3.
5 x1, x2 = -2, 3
6
7 # Начнем с x1=-2 и x2=3. Найдём середину этого диапазона, M = 0.5.
8 M = 0.5
9
10 # Соответственно переназначим границы диапазона x1 и x2
11 # Если 10**0.5<Y, значит ответ лежит в диапазоне от 0.5 до 3,
12 if 10 ** 0.5 < Y:
13 x1, x2 = 0.5, 3
14 # а если 10**0.5⩾Y — в диапазоне от -2 до 0.5.
15 else:
16 x1, x2 = -2, 0.5
17
18 # и снова проверим новую середину M.
19 # Если 10**M<Y, ответ лежит между M и x2,
20 # а если 10**M⩾Y — между x1 и M.
21 # Будем повторять это последнее действие до тех пор,
22 # пока размер диапазона x2-x1 не окажется меньше 0.0000001.
Во-первых, лишнее присваивание — меняется только x2 или только x1
Во-вторых, если присмотреться к продолжению спойлера (три строчки со слов «и снова…»), можно заметить, что там ещё раз описаны те же самые действия, но на этот раз с использованием переменных, а не чисел. Так что часть уже написанного явно избыточна
Можно было сразу формулировать алгоритм про x1 , x2 и M:
1 # Не забудем ввести Y
2 Y = float(input())
3
4 # Для Y из диапазона 1/100…1000 x не может быть меньше -2 или больше 3.
5 x1, x2 = -2, 3
6
7 # Начнем с x1=-2 и x2=3. Найдём середину этого диапазона, M = 0.5.
8 M = x1 + (x2 - x1) / 2
9
10 # Соответственно переназначим границы диапазона x1 и x2
11 # Если 10**M<Y, ответ лежит между M и x2,
12 if 10 ** 0.5 < Y:
13 x1 = M
14 # а если 10**M⩾Y — между x1 и M.
15 else:
16 x2 = M
17
18 # Будем повторять это последнее действие до тех пор,
19 # пока размер диапазона x2-x1 не окажется меньше 0.0000001.
Часть алгоритма (начинающуюся с if …) нужно выполнять много раз, пока x1 не приблизится к x2. В Python проверка условия пишется в начале цикла:
1 # Не забудем ввести Y
2 Y = float(input())
3
4 # Для Y из диапазона 1/100…1000 x не может быть меньше -2 или больше 3.
5 x1, x2 = -2, 3
6
7 # Начнем с x1=-2 и x2=3. Найдём середину этого диапазона, M = 0.5.
8 M = x1 + (x2 - x1) / 2
9
10 # Будем повторять это последнее действие до тех пор,
11 # пока размер диапазона x2-x1 не окажется меньше 0.0000001.
12 while x2 - x1 >= 1e-7:
13 # Если 10**M<Y, ответ лежит между M и x2,
14 if 10 ** M < Y:
15 x1 = M
16 # а если 10**M⩾Y — между x1 и M.
17 else:
18 x2 = M
19
20 print(M)
1e-7 — это представление вещественного числа в виде мантиссы и порядка
мантиссаeпорядок = мантисса*10порядок
- можно было написать 0.0000001, если не лень считать нули
- Не забываем о том, что вся внутренность цикла должна быть с отступом
Программа теперь запускается, но молчит и не останавливается! Можем поставить в конце цикла отладочную выдачу, чтобы посмотреть, чему равны наши переменные
1 # Не забудем ввести Y
2 Y = float(input())
3
4 # Для Y из диапазона 1/100…1000 x не может быть меньше -2 или больше 3.
5 x1, x2 = -2, 3
6
7 # Начнем с x1=-2 и x2=3. Найдём середину этого диапазона, M = 0.5.
8 M = x1 + (x2 - x1) / 2
9
10 # Будем повторять это последнее действие до тех пор,
11 # пока размер диапазона x2-x1 не окажется меньше 0.0000001.
12 while x2 - x1 >= 1e-7:
13 # Если 10**M<Y, ответ лежит между M и x2,
14 if 10 ** M < Y:
15 x1 = M
16 # а если 10**M⩾Y — между x1 и M.
17 else:
18 x2 = M
19 print(x1, x2, M)
20 print(M)
- Получим бесконечное
0.5 3 0.5 0.5 3 0.5 0.5 3 0.5 …
Оказывается, мы не вполне правильно отформатировали спойлер (или зря удалили фразу «снова проверим новую середину»). Стартовые значения x1 и x2 должны определяться в начале программы, а вот M — середина отрезка — вычисляться заново внутри цикла:
1 # Не забудем ввести Y
2 Y = float(input())
3
4 # Для Y из диапазона 1/100…1000 x не может быть меньше -2 или больше 3.
5 # Начнем с x1=-2 и x2=3.
6 x1, x2 = -2, 3
7
8 # Будем повторять это последнее действие до тех пор,
9 # пока размер диапазона x2-x1 не окажется меньше 0.0000001.
10 while x2 - x1 >= 1e-7:
11 # Найдём середину этого диапазона, M
12 M = x1 + (x2 - x1) / 2
13
14 # Если 10**M<Y, ответ лежит между M и x2,
15 if 10 ** M < Y:
16 x1 = M
17 # а если 10**M⩾Y — между x1 и M.
18 else:
19 x2 = M
20 print(M)
Эта программа работает!