Как быстро найти любой логарифм с помощью обычного цикла

Как быстро найти любой логарифм с помощью обычного цикла

Пишем простой код на Python

На прошлой неделе мы рассказали, что такое логарифм и зачем он нужен. Сегодня найдём логарифм с помощью программирования. 

Вот короткая версия теории:

  1. Логарифм — это в какую степень нужно возвести одно число, чтобы получить другое число.
  2. То, число, которое возводят в степень, называется основанием логарифма.
  3. Логарифм обозначается словом log.
  4. Например, log(10) 100 = 2, потому что 10² = 100.
  5. Есть ещё обозначение lg — это то же самое, что log(10). И есть ln — это то же самое, что log(e), где e — это число Эйлера, важная математическая константа. 
  6. Логарифмы используются в каждой значимой области нашей жизни, от биологии до физики.

Теперь, когда мы знаем достаточно про логарифм, то можем написать программу, которая нам найдёт любой логарифм по любому основанию.

В чём идея

Мы уже выяснили, что логарифм — это степень, в которую нужно возвести основание логарифма, чтобы получить нужное число. Получается, что нам нужно подобрать такую степень, чтобы при возведении она давала такое же число — это и будет ответом к решению логарифма.

Алгоритм поиска будет таким: 

  1. Найдём минимальное значение степени, возведение в которую ещё не превысит наше число.
  2. Это значит, что следующее за ним целое число — уже перебор, и основание в этой степени точно превысит наше число.
  3. Будем делить этот промежуток пополам нужное количество раз, пока не получим нужную точность ответа после запятой.
  4. Когда цикл закончится, середина оставшегося промежутка и будет ответом.

Мы так уже делили границы пополам в задаче про то, как угадать число за 7 попыток, поэтому, если алгоритм показался немного непонятным, — перечитайте то решение и возвращайтесь сюда.

Готовим переменные

Для работы программы пользователь должен будет указать три вещи:

  1. Основание логарифма.
  2. Число, от которого мы берём этот логарифм.
  3. Точность решения. Точность указываем в количестве точно вычисленных знаков после запятой.

Выделим переменные для этого: 

# на старте границы поиска значения логарифма все равны нулю
start = 0
end = 0
middle = 0

# логарифм какого числа мы ищем
num = 600
# основание логарифма
base = 10

# сколько нужно знаков после запятой
accuracy = 4

Вычисляем границы

Поиск делаем так: начинаем считать от нуля и на каждом шаге увеличиваем это значение на единицу. Как только мы превысили аргумент (то, от чего берём логарифм) — это наша конечная граница. Соответственно, предыдущее значение, которое на единицу меньше, будет стартовой границей.

# пока основание в очередной степени не превысило само число — 
while base**end <= num:
    # увеличиваем конечную границу поиска на единицу
    end += 1

# откатываемся на один шаг назад от конечной границы, чтобы найти начальную границу
start = end - 1

Проверяем, вдруг мы сразу нашли решение

На всякий случай перед тем, как идти дальше, проверим, будет ли решением наша стартовая граница — это сразу может сэкономить нам много сил в дальнейшем:

Проверяем, вдруг мы сразу нашли решение
На всякий случай перед тем, как идти дальше, проверим, будет ли решением наша стартовая граница — это сразу может сэкономить нам много сил в дальнейшем:
# если сразу нашли целое значение степени
if base**start == num:
    # выводим решение
    print('log(' + str(base) + ')' + str(num) + ' = ' + str(start))
    # останавливаем программу
    exit(0)

Считаем логарифм

Мы будем считать логарифм не классическим способом из высшей математики, а простым приближением — найдём ответ с приемлемой точностью. За точность отвечает переменная accuracy, но в цикле мы её умножим на 4. Это неочевидный ход, поэтому сейчас объясним, в чём тут дело.

На каждом шаге цикла мы делим границу пополам, но если деление выпадает на чётную значимую цифру, то при делении у нас не увеличится количество знаков после запятой. Например, если нам нужна точность 2 знака после запятой, то если вторым шагом цикла мы разделим 0,4 на 2, то у нас останется один знак после запятой (0,2). Таких делений может быть 4 подряд, прежде чем мы доберёмся до следующего знака: 8 → 4 → 2 → 1, поэтому мы и умножаем требуемую точность на 4 — чтобы гарантированно получить нужную точность.

Теперь запишем этот цикл на языке программирования. Его можно было сделать изящнее, например, вложив условные операторы друг в друга или используя оператор множественного выбора, но так получается нагляднее:

# организуем цикл, чтобы получить нужную точность после запятой
for i in range(accuracy*4):
    # увеличиваем счётчик цикла
    i += 1
    # находим серединное значение
    middle = (start + end) / 2
    # если основание в этой степени больше нашего числа, то сдвигаем к середине конечную границу
    if base**middle > num:
        end = middle
    # если основание в этой степени больше нашего числа, то сдвигаем к середине начальную границу
    if base**middle < num:
        start = middle
    # если основание в этой степени равно нашему числу
    if base**middle == num:
        # выводим ответ и выходим из цикла
        print('log(' + base + ')' + num + ' = ' + start)
        break

Выводим ответ

Это самая простая часть алгоритма:

# когда цикл закончился — выводим ответ
print('log(' + str(base) + ')' + str(num) + ' = ' + str(middle))

Проверяем работу

Для проверки посчитаем log(10) 600 с помощью нашей программы:

Как быстро найти любой логарифм с помощью обычного цикла
Ответ программы — 2,77815 с точностью 5 знаков после запятой

Теперь запустим калькулятор и проверим наше решение:

Как быстро найти любой логарифм с помощью обычного цикла
Первые 5 знаков после запятой — те же самые, значит? Алгоритм работает верно

# на старте границы поиска значения логарифма все равны нулю
start = 0
end = 0
middle = 0

# логарифм какого числа мы ищем
num = 600
# основание логарифма
base = 10

# сколько нужно знаков после запятой
accuracy = 5

# пока основание в очередной степени не превысило само число — 
while base**end <= num:
    # увеличиваем конечную границу поиска на единицу
    end += 1

# откатываемся на один шаг назад от конечной границы, чтобы найти начальную границу
start = end - 1

# если сразу нашли целое значение степени
if base**start == num:
    # выводим решение
    print('log(' + str(base) + ')' + str(num) + ' = ' + str(start))
    # останавливаем программу
    exit(0)

# организуем цикл, чтобы получить нужную точность после запятой
for i in range(accuracy*4):
    # увеличиваем счётчик цикла
    i += 1
    # находим серединное значение
    middle = (start + end) / 2
    # если основание в этой степени больше нашего числа, то сдвигаем к середине конечную границу
    if base**middle > num:
        end = middle
    # если основание в этой степени больше нашего числа, то сдвигаем к середине начальную границу
    if base**middle < num:
        start = middle
    # если основание в этой степени равно нашему числу
    if base**middle == num:
        # выводим ответ и выходим из цикла
        print('log(' + base + ')' + num + ' = ' + start)
        break

# когда цикл закончился — выводим ответ
print('log(' + str(base) + ')' + str(num) + ' = ' + str(middle))

Текст:

Михаил Полянин

Редактор:

Максим Ильяхов

Художник:

Даня Берковский

Корректор:

Ирина Михеева

Вёрстка:

Кирилл Климентьев

Соцсети:

Алина Грызлова

Любите математику? Это для вас
Попробуйте бесплатный тренажер «Основы математики для цифровых профессий». Это все необходимые знания, чтобы закрыть пробелы в математике для айтишника.
Попробовать бесплатно
Любите математику? Это для вас Любите математику? Это для вас Любите математику? Это для вас Любите математику? Это для вас
Получите ИТ-профессию
В «Яндекс Практикуме» можно стать разработчиком, тестировщиком, аналитиком и менеджером цифровых продуктов. Первая часть обучения всегда бесплатная, чтобы попробовать и найти то, что вам по душе. Дальше — программы трудоустройства.
Начать карьеру в ИТ
Получите ИТ-профессию Получите ИТ-профессию Получите ИТ-профессию Получите ИТ-профессию
Еще по теме
Ещё больше полезных CSS-команд
Ещё больше полезных CSS-команд

Короткие и мощные.

hard
Ваш собственный телеграм-секретарь: делаем вместе
Ваш собственный телеграм-секретарь: делаем вместе

Пошаговая инструкция для тех, кому нужен секретарь.

easy
Uncaught SyntaxError: Unexpected end of input — что это значит?
Uncaught SyntaxError: Unexpected end of input — что это значит?

Скорее всего, вы забыли закрыть скобки при объявлении функции.

easy
Пианино на JavaScript для Chrome
Пианино на JavaScript для Chrome

Не «Мир Дикого запада», но тоже сгодится.

medium
Что означает ошибка SyntaxError: missing ) after formal parameters

На самом деле это не просто пропущенная скобка.

easy
Делаем сами: адаптивный сайт

С котиками!

medium
Что означает ошибка IndentationError: expected an indented block
Что означает ошибка IndentationError: expected an indented block

Самая популярная ошибка у начинающих программистов на Python.

easy
Простой калькулятор на JavaScript
Простой калькулятор на JavaScript

Проще уже некуда

easy
Подключаем к сайту орфокорректор. Орфонейрокорректор!

Пишите как угодно — нейронка никому не расскажет.

hard
Пишем код: как поменять местами значения переменных
Пишем код: как поменять местами значения переменных

Что делать, если третью переменную использовать нельзя.

medium
easy