1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6

# теория · шаг 3 из 6

Модель стоимости и старший член

Коротко

Точная формула T(n) выходит громоздкой - an² + bn + c с неизвестными константами. Её огрубляют по двум причинам. Константы зависят от машины и от того, что назвали шагом, - значит несут не про алгоритм, а про железо. А из слагаемых на большом n решает только старшее: n² растёт так быстро, что bn и c рядом с ним теряются. Поэтому в ответе оставляют один старший член без множителя - «порядок роста».

Если знаешь, что считается шагом в RAM-модели и почему в оценке оставляют один старший член без константы - листай до «Теперь сам».

Как думаешь, какая быстрее

Две программы: первой нужно 100·n шагов, второй - n². Какая быстрее? Вопрос с подвохом: при n = 10 первой нужно 1000 шагов, второй - 100, второй быстрее в десять раз. А при n = 1000 первой - 100 000, второй - миллион, и теперь быстрее первая. Где-то посередине они сравнялись. Найди эту границу - и станет видно, что «быстрее» без указания размера входа ничего не значит.

На что это похоже

Старший член - это как старший разряд числа. Сравнивая 3 000 000 и 90 000, ты не складываешь все цифры: у первого числа семь разрядов, у второго пять, и первое больше, что бы ни стояло в младших разрядах. В формуле T(n) роль разряда играет степень n: слагаемое с n² при большом n крупнее любого слагаемого с n, как миллионы крупнее тысяч.

Механизм 1: что честно считать шагом

Прежде чем огрублять, надо знать, что мы вообще считаем. Договорённость - RAM-модель (её ввёл раздел про модель вычислителя): за один шаг берутся арифметика, сравнение, присваивание, переход и обращение к ячейке памяти по номеру. Всё это - операции, чья цена не зависит от n. Операция, объём работы которой растёт с данными, шагом быть не может: проход по списку стоит столько элементов, сколько просмотрел.

У модели есть одна честная оговорка. Она считает арифметику над одним числом единицей - это верно, пока числа влезают в машинное слово. Над числами в тысячи цифр (криптография) сложение уже стоит длины числа, и тогда берут более тонкую модель. Для этого курса, где данные - это списки из n элементов обычного размера, единичной цены хватает; где перестанет хватать, урок скажет отдельно.

Механизм 2: почему решает старший член

Старший член - это слагаемое формулы T(n), растущее быстрее всех остальных (у 3n² + 500n + 2000 это 3n²). Пусть точный счёт дал T(n) = 3n² + 500n + 2000. Подставим растущие n:

n 3n² 500n 2000 доля 3n²
10 300 5 000 2 000 4%
100 30 000 50 000 2 000 37%
1 000 3 000 000 500 000 2 000 86%
100 000 3·10¹⁰ 5·10⁷ 2 000 99,8%

На маленьком входе решают младшие слагаемые, на большом - старшее, и чем больше n, тем полнее. Причина в скорости роста: увеличив n в десять раз, ты умножаешь n² на сто, а n - только на десять. Разрыв не сокращается, а растёт, поэтому доля старшего слагаемого стремится к целому. Младшие слагаемые и множитель 3 не меняют этого вывода - они лишь двигают границу, с которой старшее побеждает.

Правило

В оценке оставляют один самый быстрорастущий член и выбрасывают множитель при нём и все младшие слагаемые. 3n² + 500n + 2000 превращается в «порядка n²». Множитель выбрасывают потому, что он про железо и про то, что назвали шагом; старший член - потому что он один и определяет рост. Формальные O, Θ и Ω для этого огрубления - в следующей главе; здесь важен сам мотив.

Разбор: где сравнялись 100n и n²

Программы из крючка равны, когда 100·n = n², то есть n = 100. До сотни элементов быстрее квадратичная (у неё меньше множитель), после сотни - линейная, и дальше разрыв только растёт: при n = 10 000 линейной нужен миллион шагов, квадратичной - сто миллионов. Вот почему порядок роста - главный ответ: он говорит, кто победит на большом входе, а на большом входе и решается, доживёт ли программа.

Разбор: когда множитель всё-таки важен

Порядок роста - первый разрез, но не последнее слово. Если два алгоритма оба линейные, но один делает 2n шагов, а другой 10n, порядок у них один, а на практике второй в пять раз медленнее - и выбор между ними идёт как раз по множителю. То же с реальными машинами: n·log n-сортировка с плохим множителем может уступать n²-сортировке на входах в десятки элементов, поэтому быстрые сортировки на маленьком куске переключаются на простую. Порядок отвечает на вопрос «что будет при большом n»; на «что быстрее прямо сейчас на моих трёхстах записях» отвечает замер.

Что ломается без этого

Одна крайность - выбрать алгоритм по одному порядку и обжечься на константе: бывают алгоритмы с прекрасным порядком роста и таким множителем, что они выгодны лишь на входах, которые не поместятся ни в один компьютер. Другая крайность - цепляться за константу и переписывать n² в n² с чуть меньшим множителем, когда сменить порядок на n·log n дало бы в тысячу раз больше. Порядок роста отсекает второе, замер спасает от первого.

Зачем это в работе

Таблица роста из отчёта машины - это и есть порядок, снятый с живой программы: данных втрое, шагов втрое (линия), вдевятеро (квадрат), чуть больше чем втрое (n·log n). По ней выбирают, что вообще имеет смысл запускать на боевом объёме, не дожидаясь, пока прод встанет. А точную формулу с константами берегут для случая, когда два решения одного порядка и спор идёт про множитель.

Теперь сам

Дано T(n) = 5n² + 1000n. Каков порядок роста и при каком n слагаемое 5n² обгоняет 1000n?

Ответ. Порядок роста - n²: это старший член, множитель 5 и слагаемое 1000n отбрасываются. Обгон - там, где 5n² = 1000n, то есть 5n = 1000, n = 200. До двухсот элементов вклад 1000n больше, после - решает 5n², и дальше разрыв только растёт. Порядок роста описывает именно это «дальше», а не поведение на первых двух сотнях.

Главное

Точную T(n) = an² + bn + c огрубляют до одного старшего члена без множителя - «порядка n²». Множитель отбрасывают, потому что он про железо и про выбор шага, а не про алгоритм; младшие слагаемые - потому что старший член растёт быстрее и на большом n их подавляет (×10 к n даёт ×100 к n², но лишь ×10 к n). Шагом при этом честно считаются операции RAM-модели, цена которых не зависит от n. Порядок роста решает, кто победит на большом входе; на маленьком последнее слово за множителем и замером.

Комментарии

Пока нет комментариев. Будь первым!

Оставить комментарий

Комментарий появится после проверки. Email не публикуется. Войти, чтобы не вводить имя каждый раз.