Я учусь в седьмом классе. По математике мы проходим линейные и квадратные уравнения, графики. Я решил заниматься дополнительно. И среди прочих задач, мне попалась задача с такими условиями: "Население страны ежегодно увеличивается на 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".