Можно ли ускорить поиск первого плохого расчета с помощью бинарного поиска
Что проверяют
Видите ли вы за словами «искать быстрее» условие, при котором бинарный поиск вообще применим, и понимаете ли, что в учётной системе дорог не перебор, а сама проверка. Вопрос типовой для разбора расхождений: итог где-то поехал, надо найти первый испорченный документ.
Как отвечать
Да, если предикат монотонный: начиная с некоторого места все расчёты плохие, а до него все хорошие. Тогда вместо N проверок хватит логарифма от N, для тысячи документов это около десяти шагов вместо тысячи.
Сформулируйте инвариант вслух: слева граница, где точно хорошо, справа граница, где точно плохо, ответ это первый плохой.
Пока Лево < Право Цикл
Середина = Лево + Цел((Право - Лево) / 2);
Если ЕстьРасхождение(Список[Середина]) Тогда
Право = Середина;
Иначе
Лево = Середина + 1;
КонецЕсли;
КонецЦикла;Две вещи в учётной задаче важнее самого алгоритма.
Проверка должна быть повторяемой и без последствий. Если шаг это перепроведение, оно пишет движения и меняет остатки, поэтому следующая итерация смотрит уже на испорченное состояние. Работают либо в транзакции с отменой, либо на копии базы, либо сверяются с заранее снятым срезом.
Искать удобнее не по номеру в массиве, а по периоду: границы задаются датой, середина это дата, проверка это сверка итогов на неё. Тогда не нужно тянуть в память весь список документов.
Где спотыкаются
Не проверяют монотонность. Если расхождение где-то гасится обратной ошибкой или сторно, предикат перестаёт быть ступенькой, и поиск уверенно сходится к случайной точке. Прежде чем ускорять, докажите словами, что после первого плохого все следующие тоже плохие.
Забывают про целочисленность. Деление в 1С даёт дробь, и без Цел() индекс окажется нецелым, а обращение к элементу упадёт. Подмена на Окр() не спасает: округление вверх на половине вернёт середину, равную правой границе, и цикл перестанет сходиться.
Ставят условие цикла и сдвиг границ вразнобой. Классика это Право = Середина вместе с условием «пока Лево меньше или равно Право»: границы перестают сближаться, и цикл висит. Пару «условие, сдвиг» подбирают вместе и проверяют руками на двух соседних элементах.