Я учусь в седьмом классе. По математике мы проходим линейные и квадратные уравнения, графики. Я решил заниматься дополнительно. И среди прочих задач, мне попалась задача с такими условиями: "Население страны ежегодно увеличивается на 1/80. Через сколько лет население страну удвоится ?" Это задача из "Сборника конкурсных задач по математике с решениями" Кущенко В. С., 1966 года издания.
Первой моей мыслью было написать программу на python, где в цикле увеличивать значение 1 на заданную величину 1/80, пока оно не достигнет 2. Она выглядит таким образом:
def pop_inc(num, denum, mult):
#num - числитель, denum - знаменатель, mult - во сколько раз должно увеличиться исходное значение cnt = 0
x = 1
while x <= mult:
x = x*(1+num/denum)
cnt += 1
return cnt
from datetime import datetime
t0 = datetime.now()
print(pop_inc(1,80,2))
print (datetime.now() - t0, "время обработки в секундах")
Время выполнения этого кода зависит от входных параметров: чем больше значение знаменателя, тем больше циклов будет выполняться в ходе работы программ. Если для значения 1/80 выполнение программы заняло 0.001 секунды, то для значения 1/100000000 это будет уже 12.6 сек, а для ещё меньшего значения программа может работать минуты и даже часы.
Очевидно, что раз эта задача - задача по математике и, тем более, из учебника 1966 года, то её никто не решал таким образом.
Собственно, идея решения уже заложена в коде выше: количествово населения "N" увеличилось в первый год на N1/80 и стало равно: N(1 + 1/80).
Во второй год это значение увеличилось ещё на 1/80: (N*(1 + 1/80))(1+1/80).
В третий год это значение увеличилось ещё на 1/80: ((N(1 + 1/80))(1+1/80))(1+1/80). Если приглядеться, то видно, что в этих расчётах есть общий множитель (1+1/80).
Лишние скобки между ними можно убрать, так как (b*a)*a равнозначно b*a*a. Таким образом, для третьего года получаем произведение:
N*(1 + 1/80)(1+1/80)(1+1/80) или N*(1 + 1/80)3.
Соответственно, в тот год n, когда количествово населения N удвоится произведение будет равно N*(1 + 1/80)n или равно 2N.
В результате получаем уравнение: N*(1 + 1/80)n = 2N
или, если сократить N: (81/80)n = 2.
То есть задача сводится к тому, что нам нужно найти "в какую степень нужно возвести значение (81/80), чтобы получилось 2?".
В седьмом классе ещё не проходят логарифмы. Но, я подглядел в ответ :) и увидел, что данное уравнение решается с помощью логарифмов. Собственно, логарифм есть, то значение степени, в которое нужно возвести основание, чтобы получить искомый результат. Итак, наше уравнение превращается в логарифм log(81/80)2 = n. Так как именно в таком виде мы его решить не можем, а нужно его привести к десятичному логарифму, то используем формулы преобразования логарифмов:
a) формула перехода к новому основанию (10) logax = lgx/lgba :
log(81/80)2 = lg2/lg(81/80)
b) формула логарифма частного lgx/y = lgx - lgy:
lg2/lg(81/80) = lg2/(lg(81)-lg(80))
Теперь напишем на python функцию нахождения решения задачи уже с помощью логарифмов и замерим производительность:
import math from datetime
import datetime
def pop_inc(num, denum, mult):
#num - числитель, denum - знаменатель, mult - во сколько раз должно увеличиться исходное значение
return round(math.log10(mult)/(math.log10(num+denum)-math.log10(denum)),0)
t0 = datetime.now()
print(pop_inc(1,80,2))
print (datetime.now() - t0, "время обработки в секундах")
Для значения 1/80 выполнение программы заняло тоже примерно 0.001 секунды, так же, как и для значения 1/100000000. Очевидно, что и для любой другой бесконечно малой величины время выполнения будет такое же, так как программа выполняется за один проход, а не в очень длинном цикле, как в первом варианте.
На этом примере я понял, что просто изучить циклы и условные операторы - это ещё не значит стать программистом.
Правда здесь возникает другая проблема :) За счёт округления логарифмов значение, получаемое в первом варианте и во вотором отличаются. В случае с параметром 1/100000000 первая функция даёт результат "69 314 719", а вторая "69 314 706".