Способы поиска ошибок
Как выявлять ошибки в алгоритме
Выявление ошибок в алгоритме возможно при помощи двух способов:
1. Использование ParamDebug
Данный способ позволяет выводить промежуточные значения алгоритма при тестировании в отладочную таблицу, а также проверять правильность логики алгоритма по этим значениям.
Рисунок 1 – Отладочная таблица
Например, выведем значения индикатора «Полосы Боллинджера» для проверки в отладочную таблицу. При наведении на какой-либо бар, в таблице выведется текущее значение индикатора на этом баре.
Рисунок 2 – Проверка значений через ParamDebug
Также, чтобы убедиться в правильности расчетов, значения в отладочной таблице данного индикатора можно сравнить со значениями готового индикатора (при его наличии) в TradingView.
Если в итоге значения с ParamDebug не сходятся, то можно в TradingView посмотреть код данного индикатора, разбить его на части и выводить промежуточные значения в TradingView. (Рисунок 4)
Процесс проверки:
1. Открываем код индикатора и делаем его копию, чтобы появилась возможность его редактировать.
Рисунок 5 – Копия кода индикатора
2. Изменяем код, например, хотим проверить значения переменной «dev» с нашим значением в ParamDebug. Значения «dev» выводится с помощью функции plot, как показано на рисунке ниже.
Рисунок 6 – Вывод значений
Таким образом, можно сравнивать промежуточные значения кода с промежуточными значениями в TradingView для проверки правильности расчетов.
Это один из вариантов проверки. Также можно сравнить значения с помощью Excel таблицы, если ТЗ в таблице и есть форма расчетов для проверки, например для расчета индикатора «Коэффициента корреляции» (рисунок 7).
Рисунок 7 – Проверка значений через Excel таблицу
Процесс проверки через Excel таблицу:
- Открываем график двух инструментов, например (BTCUSDT и BNBUSDT);
- Подставляем значения закрытой свечи (кол-во зависит от периода расчета) этих двух инструментов в таблицу;
- Сверяем значения xi, yi, xi*yi, x2, y2 со значениями, выведенными в ParamDebug.
Бывают такие ситуации, когда при проверке выше указанными способами, промежуточные и итоговые значения совпадают, но алгоритм не правильно работает. Один из вариантов ошибки, это использование глобальной переменной, которая принимает какие-то значения в методе при определенном условии, но при вызове функции с другим параметром, алгоритм не срабатывает. Данную ошибку можно найти при помощи покрытия разных участков кода ParamDebug и использовании отладки в Visual Studio.
Например, у нас есть несколько объектов класса и функция, принимающая данные объекты, которая вызывается каждый бар.
В данном случае, при таймфрейме 1 и 5 минут, переменная _date будет перезаписываться каждую минуту и расчет будет верным только для 1 минуты, а для 5 минуты условие никогда не будет true. Таким образом, алгоритм будет рассчитывать только для 1 минуты. Исправить это можно, если переменную _date вынести в класс, чтобы каждый объект сохранял информацию по тому таймфрейму, который ему ранее присвоился.
Таким образом, глобальные переменные, используемые в расчетах функциях, принимающие разные таймфреймы, переносить в класс.
2. Использование модуля для отладки кода через Visual Studio
Данный способ позволяет тестировать/проверять значения с помощью break points в Visual Studio. Можно комбинировать с выше описанными способами проверки.
Отладка скрипта через Visual Studio
Рисунок 8 — отладка в Visual Studio
Подключение модуля для отладки показано будет в другой статье.
Check List:
- Покрыть код ParamDebug, где требуется проверить правильность работы алгоритма
- Сравнить значения с TradingView (при наличии существующего скрипта) и разбить код на части, выводить промежуточные значения
- Использовать Excel (если есть расчеты)
- Debug в Visual Studio
Пример поиска ошибка через ParamDebug или отладки в Visual Studio:
Данное покрытие кода позволяет просмотреть разные участки кода, которые будут выполняться. Если на отладочной таблице в ETS будет видно, к примеру, ParamDebug(«Test», 1) и не видно ParamDebug(«Test», 2), это означает, что номер бара меньше указанного значения. Таким способом, покрывая ParamDebug можно идти в глубину кода и просматривать, в какие моменты код срабатывает или нет.
Check List ParamDebug/отладка в Visual Studio:
- Покрыть те участки кода, где необходимо посмотреть исполнения кода;
- Если выполняется код до функции, но функция пропускается, то углубляться в данную функцию и покрывать ее ParamDebug;
- Также углублять в подфункции (при наличии);
- Просматривать значения переменных, при которых не выполняется код;
- Сравнивать значения выше указанными способами (Excel, TradingView).
Check List Excel:
- Заполнять таблицу необходимыми значениями при расчетах;
- Разбивать формулу расчета на части;
- Сверять значения каждой части формулы с полученными.
Check List TradingView (при наличии готового кода):
- Найти индикатор;
- Скопировать скрипт, чтобы в дальнейшем изменять;
- Разбить алгоритм на части;
- Выводить промежуточные значения на график и сверять со своими промежуточными.
Все возможности открывает платформа ETS.
Основной инструмент при поиске ошибок в коде
Данная статья рассчитана на начинающих, однако, определённый опыт программирования уже надо иметь. И мне хотелось бы рассказать об одном потрясающем инструменте поиска ошибок. Имееются ввиду те ошибки, которые связаны с алгоритмом, а не с синтаксисом (забыли точку с запятой, не закрыли кавычки, скобки и так далее). Вот в этой статье я расскажу о своём (да и любого другого, кто уже давно программирует) основном инструменте поиска ошибок в коде.
Итак, давайте определимся, какие же ошибки мы будем искать. Допустим, мы написали функцию, цель которой складывать два числа и возвращать результат. Давайте её напишем (в коде специально сделана ошибка):
<?php
function summa($x, $y) {
$sum = $x + $y;
return $x;
}
echo summa(5, 4);
?>
В результате, мы видим, что у нас вывелось 5, хотя мы хотели увидеть 9 (5 + 4). Данный код очень простой, поэтому, конечно, здесь Вы легко сразу обнаружите ошибку. Однако, данный пример является не более, чем примером. Его задача рассказать о механизме поиска ошибок в алгоритме. Так вот, мы должны выяснить, на каком шаге происходит ошибка. И это делается с помощью просмотра значения переменных на каждом шаге. Вот пример того, что нужно делать, чтобы найти ошибку:
<?php
function summa($x, $y) {
echo $x." - ";
echo $y." - ";
$sum = $x + $y;
echo $sum;
return $x;
}
echo summa(5, 4);
?>
Далее мы анализируем каждый вывод переменной:
- Так, переменная x выдала значение 5. Следовательно, эта переменная передалась верно.
- Переменная y имеет значение 4, что так же верно, ведь именно 4 мы и передавали.
- И, наконец, переменная sum показала значение 9. Это то самое значение, которое является истинным.
Дальше идёт return, следовательно, ошибка именно в этой строке. До неё всё шло прекрасно, следовательно, внимательно приглядываемся к этой строке и видим, что вместо того, чтобы возвращать значение переменной sum, мы возвращаем переменную x.
Итак, подведём итог. Основным инструментом поиска ошибок является оператор echo (либо функция print_r(), если переменная является массивом). Всё, что нужно, это просто смотреть на необходимую переменную на каждом шаге алгоритма. И понять, на каком моменте возникает ошибка. Если, допустим, ничего вообще не выводится, то это значит, что функция даже не вызывается. Следовательно, ищем ошибку там, где она должна была вызваться.
Данный подход к устранению ошибок в алгоритме я использую постоянно, нет ни одной программы (скрипта), разве что совсем простого, где я бы данный подход не использовал. Более того, данный подход является универсальным и подходит для других языков тоже. Поэтому его надо освоить Вам в самые кратчайщие сроки, чего я Вам искренне и желаю.
-
Создано 01.09.2011 23:17:13
-
Михаил Русаков
Копирование материалов разрешается только с указанием автора (Михаил Русаков) и индексируемой прямой ссылкой на сайт (http://myrusakov.ru)!
Добавляйтесь ко мне в друзья ВКонтакте: http://vk.com/myrusakov.
Если Вы хотите дать оценку мне и моей работе, то напишите её в моей группе: http://vk.com/rusakovmy.
Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновления
Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.
Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):
-
Кнопка:
Она выглядит вот так:
-
Текстовая ссылка:
Она выглядит вот так: Как создать свой сайт
- BB-код ссылки для форумов (например, можете поставить её в подписи):
PROGRAM MAIN
IMPLICIT NONE
! triangle parameters
REAL a, b, c, d, f
COMMON /TRIANGLE/ a, b, d
REAL CosMinAngle, q1, q2, q3
! function declaration
REAL Area, MinAngle
REAL Side
INTEGER NUM
CALL TriangleInput()
DO WHILE (.TRUE.)
CALL MENU
! reading command number
READ *, NUM
PRINT *
! process input
SELECT CASE(NUM)
CASE(1)
CALL TriangleInput
CASE(2)
f = AREA(a, b, d)
PRINT *,'Area of a triangle: ', f
CASE(3)
CALL MinAngle()
PRINT *,'Minimum triangle angle: ', MinAngle()
CASE(4)
CALL CosMinAngle()
PRINT '(A,$)','Cosine of minimum angle: '
PRINT *, CosMinAngle()
CASE(5)
PRINT *, 'Enter one of the 2 sides and angle: '
READ *, a, b , d
c = Side(a, b, d)
PRINT *,'The 3rd side of the triangle: ', Side()
CASE(6)
PRINT *, 'Goodbuy!'
STOP
CASE DEFAULT
PRINT *, 'Number entered incorrectly'
END SELECT
END DO
END
SUBROUTINE MENU
IMPLICIT NONE
! display the menu
PRINT '(/,A,$)','Enter one of the suggested commands:'
PRINT *
PRINT *,'1. Entering a new triangle'
PRINT *,'2. Triangle area calculation'
PRINT *,'3. Minimum angle calculation'
PRINT *,'4. Cosine calculation of the minimum angle'
PRINT *,'5. Find the 3rd side of the triangle'
PRINT *,'6. Exit'
END
! Entering a new triangle
SUBROUTINE TriangleInput
IMPLICIT NONE
REAL a, b, d
COMMON /TRIANGLE/ a, b, d
REAL c, Side
DO WHILE (.TRUE.)
PRINT *,'Enter the two sides and an angle: '
READ *, a, b, d
c = Side(a, b, d)
! triangle existence test
IF (((a+b).GE.c).AND.((a+c).GE.b).AND.((b+c).GE.a))THEN
PRINT *, 'Triangle set.'
RETURN
ELSE
PRINT *, 'The triangle does not exist'
RETURN
END IF
END DO
END
! Triangle area calculation
REAL FUNCTION Area()
IMPLICIT NONE
REAL a, b, d
COMMON /TRIANGLE/ a, b, d
REAL Pi
PARAMETER (Pi = 3.141592652)
Area = 1/2*(a*b*SIN(d))
RETURN
END
! Minimum angle calculation
REAL FUNCTION MinAngle()
IMPLICIT NONE
REAL a, b, d
COMMON /TRIANGLE/ a, b, d
REAL CosMinAngle
REAL Pi, f
PARAMETER (Pi = 3.141592652)
MinAngle = ACOS(CosMinAngle())*180/Pi
RETURN
END
! Cosine calculation of the minimum angle
REAL FUNCTION CosMinAngle()
IMPLICIT NONE
REAL a, b, c, d
COMMON /TRIANGLE/ a, b, d
REAL q1, q2, q3, Side
c = Side(a, b, d)
! Find the minimum side of the triangle
IF (a .LT. b) THEN
IF (a .LT. c) THEN
q1 = a
q2 = b
q3 = c
ELSE
q1 = c
q2 = a
q3 = b
END IF
ELSE
IF (b .LT. c) THEN
q1 = b
q2 = a
q3 = c
ELSE
q1 = c
q2 = a
q3 = b
END IF
END IF
CosMinAngle = (q3**2 + q2**2 - q1**2) / (2 * q3 * q2)
RETURN
END
! Find the 3rd side of the triangle
REAL FUNCTION Side()
IMPLICIT NONE
REAL a, b, d
COMMON /TRIANGLE/ a, b, d
Side = SQRT(a**2+b**2-2*a*b*COS(d))
RETURN
END
На ввод: 2 стороны и угол между ними. Найти площадь (area), косинус минимального угла, минимальный угол и 3 сторону треугольника. Подпрограмма для вычисления площади выдает ноль. Остальные подпрограммы выдают значения при Rad (радианах), поэтому третья сторона получается неправильной (например, для 3 4 90 3-я сторона равна 5,8, хотя должно быть 5). Если вводить угол в радианах, то можно получить приближенные значения минимального угла и косинуса, но при вычислении неизвестной стороны выходит большая погрешность (например, при 3 4 1,57 3-я сторона = 3.4688246, а не 5)
Получив приказ
исполнить алгоритм, компьютер выполняет
следующие действия:
-
Находит в памяти
алгоритм с указанным именем. -
Проверяет,
соблюдаются ли начальные условия,
указанные в строке дано
(в примерах
этого параграфа в дано
пишутся
только комментарии, но позднее мы
научимся помещать там условия, которые
компьютер сможет проверять). -
Последовательно
читает команды после строки нач
и передает
их исполнителю. Каждый такой приказ на
выполнение команды называется вызовом
этой команды. -
Встретив строку
кон,
проверяет,
достигнута ли цель алгоритма, указанная
в строке надо
(см. примечание
к п. 2). -
Заканчивает
выполнение алгоритма.
Пример.
Компьютер
получает приказ исполнить алгоритм
«ход конем».
-
Компьютер находит
в памяти алгоритм А1. -
В строке дано
записан
комментарий — компьютер его пропускает. -
Компьютер
последовательно командует Роботу
вправо,
вправо, вниз.
Робот
исполняет
эти команды. -
В строке надо
помещен
комментарий — компьютер его пропускает. -
Компьютер
заканчивает выполнение алгоритма «ход
конем».
7.6. Ошибки в алгоритмах
Если при составлении
алгоритма мы случайно вместо вниз
напишем внис
или вместо вправо
— направо,
то компьютер нашу запись не поймет и,
даже не приступая к выполнению алгоритма,
сообщит об ошибке. Ошибки в записи
алгоритма называются синтаксическими.
Но даже если все
команды записаны правильно, это еще не
значит, что алгоритм составлен без
ошибок. Ошибки в составлении алгоритма
называются логическими.
Иногда логическая
ошибка может привести к отказу
— невозможности
выполнить очередную команду. Например,
при попытке выполнить алгоритм «ход
конем» (А1) в обстановке, изображенной
на рисунке 2, компьютер попытается
последовательно вызвать команды вправо,
вправо, вниз.
Однако вторую команду вправо
Робот выполнить
не сможет — возникает отказ. Получив
от исполнителя сигнал отказа, компьютер
сообщает об ошибке и прекращает выполнение
алгоритма.
Рис. 2
У каждого исполнителя
могут быть свои причины отказов. Отказ
Робота
возникает
при попытке идти сквозь стену.
Ошибки в алгоритме
не всегда приводят к отказам. Возможны
логические ошибки, не обнаруживаемые
компьютером ни до, ни во время выполнения
алгоритма. Так, если в алгоритме А1 мы
вместо вправо
случайно напишем влево,
то компьютер выполнит алгоритм, Робот
из клетки А
переместится в клетку В (см. рис. 2), но
никаких сообщений об ошибках мы не
получим (да и откуда компьютеру знать,
куда мы на самом деле хотели переместить
Робота!).
В правильно
составленных алгоритмах никаких ошибок
быть не должно. Но если синтаксические
ошибки обычно легко устранимы, то поиск
и устранение логических ошибок могут
оказаться весьма трудным делом. Таким
образом, все возможные ошибки можно
представить в виде таблицы:
Таблица 1. Ошибки
в алгоритмах.
№ |
Смысл ошибки |
Название |
Пример |
1 |
Цель не достигнута |
Логическая |
Робот не попал |
2 |
Команда не входит |
Синтаксическая |
наверх, направо |
3 |
Авария при попытке |
Семантическая |
Попытка пройти |
Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]
- #
- #
- #
- #
- #
- #
- #
- #
- #
- #
- #
Автор материалов — Лада Борисовна Есакова.
Самая распространенная ошибка, которую нужно найти и исправить – это неправильное использование вложенных условных операторов. Для усложнения поиска возможно неправильное форматирование текста (неправильно поставленные отступы).
Для того, чтобы найти ошибку, нужно поставить в соответствие друг другу все части условного оператора if и else.
Помним, что часть else относится к ближайшему if. При этом наличие части else не обязательно.
Кроме того, часто присутствует ошибка при вводе или выводе. Обязательно нужно проверить, та ли информация выводится на экран.
Особого внимания требует инициализация переменных.
Формат книги не позволяет рассмотреть все основные типы задач 2 части, рассмотрим лишь те, которые встречались на проверочных и экзаменационных работах последних двух лет.
Пример 1.
На обработку поступает положительное целое число, не превышающее 109. Нужно написать программу, которая выводит на экран сумму цифр этого числа, меньших 7. Если в числе нет цифр, меньших 7, требуется на экран вывести 0. Программист написал программу неправильно. Ниже эта программа для Вашего удобства приведена на пяти языках программирования.
Бейсик |
Python |
DIM N, DIGIT, SUM AS LONG
INPUT N SUM = 0 WHILE N > 0 DIGIT = N MOD 10 IF DIGIT < 7 THEN SUM = SUM + 1 END IF N = N 10 WEND PRINT DIGIT |
N = int(input())
sum = 0 while N > 0: digit = N % 10 if digit < 7: sum = sum + 1 N = N // 10 print(digit) |
Паскаль |
Алгоритмический язык |
var N, digit, sum: longint;
begin readln(N); sum := 0; while N > 0 do begin digit := N mod 10; if digit < 7 then sum := sum + 1; N := N div 10; end; writeln(digit) end. |
алг
нач цел N, digit, sum ввод N sum := 0 нц пока N > 0 digit := mod(N,10) если digit < 7 то sum := sum + 1 все N := div(N,10) кц вывод digit кон |
Си |
|
#include
int main() { int N, digit, sum; scanf(«%d», &N); sum = 0; while (N > 0) { digit = N % 10; if (digit < 7) sum = sum + 1; N = N / 10; } printf(«%d»,digit); return0; } |
Последовательно выполните следующее.
1. Напишите, что выведет эта программа при вводе числа 456.
2. Приведите пример такого трёхзначного числа, при вводе которого программа выдаёт верный ответ.
3. Найдите все ошибки в этой программе (их может быть одна или несколько). Известно, что каждая ошибка затрагивает только одну строку и может быть исправлена без изменения других строк. Для каждой ошибки:
1) выпишите строку, в которой сделана ошибка;
2) укажите, как исправить ошибку, т.е. приведите правильный вариант строки.
Достаточно указать ошибки и способ их исправления для одного языка программирования. Обратите внимание, что требуется найти ошибки в имеющейся программе, а не написать свою, возможно, использующую другой алгоритм решения. Исправление ошибки должно затрагивать только строку, в которой находится ошибка.
Решение:
Решение использует запись программы на Паскале. Допускается использование программы на любом из четырёх других языков.
1. Программа выведет число 4.
2. Пример числа, при вводе которого программа выдаёт верный ответ: 835.
Программа работает неправильно из-за неверной выводимой на экран переменной и неверного увеличения суммы. Соответственно, программа будет работать верно, если в числе старшая цифра (крайняя левая) равна сумме цифр, меньших 7.
3. В программе есть две ошибки.
Первая ошибка. Неверное увеличение суммы.
Строка с ошибкой:
sum := sum + 1;
Верное исправление:
sum := sum + digit;
Вторая ошибка. Неверный вывод ответа на экран.
Строка с ошибкой:
writeln(digit)
Верное исправление:
writeln(sum)
Пример 2.
Для заданного положительного вещественного числа A необходимо найти максимальное целое число K, при котором выполняется неравенство
(при K = 0 сумма считается равной 0).
Для решения этой задачи ученик написал такую программу.
Бейсик |
Python |
DIM A, S AS DOUBLE
DIM K AS INTEGER INPUT A K = 1 S = 1 WHILE S < A S = S + 1.0/K K = K + 1 WEND PRINT K END |
a = float(input())
k = 1 s = 1 while s < a: s = s + 1.0/k k = k + 1 print(k) |
Алгоритмический язык |
Паскаль |
алг
нач вещ a, s цел k ввод a k := 1 s := 1 нц пока s<a s := s + 1.0/k k := k + 1 кц вывод k кон |
var a, s: real;
k: integer; begin read(a); k := 1; s := 1; while s<a do begin s := s + 1.0/k; k := k + 1; end; write(k); end. |
Си |
|
#include <stdio.h>
int main(){ double a, s; int k; scanf(«%lf»,&a); k = 1; s = 1; while (s<a) { s = s + 1.0/k; k = k + 1; } printf(«%d», k); return 0; } |
Последовательно выполните следующее.
1. Напишите, что выведет эта программа при вводе числа 1.2.
2. Приведите пример числа, при вводе которого программа даст верный ответ.
3. Найдите в программе все ошибки (их может быть одна или несколько).
Для каждой ошибки выпишите строку, в которой она допущена, и приведите эту же строку в исправленном виде.
Обратите внимание: вам нужно исправить приведённую программу, а не написать свою. Вы можете только исправлять ошибочные строки; удалять строки или добавлять новые строки нельзя. Постарайтесь также не внести новые ошибки – за это оценка снижается.
Решение:
Решение использует запись программы на Паскале. Допускается использование программы на других языках.
1. При вводе числа 1.2 программа выведет число 2.
2. Примеры чисел, при вводе которых программа выводит верный ответ: 1.6, 2.05.
Программа содержит две ошибки, одна из которых приводит к увеличению ответа, другая – к уменьшению.
В некоторых случаях эти ошибки компенсируют друг друга, и ответ оказывается правильным. Это происходит, если значение A попадает в один из следующих диапазонов: 1.5 < A < 1.83, 2 < A < 2.08.
3. Программа содержит две ошибки.
1) Неверная инициализация. Начальное значение S должно быть равно нулю.
В приведённом варианте вычисленная сумма оказывается на 1 больше правильного значения.
Строка с ошибкой:
s := 1;
Правильная строка:
s := 0;
2) Неверное определение ответа. Приведённая программа находит не максимальное K, при котором выполняется неравенство, а минимальное, при котором оно не выполняется, то есть увеличивает верное значение на 1.
Кроме того, использованный порядок действий в цикле (увеличение K после увеличения S) приводит к увеличению ещё на 1. Это можно было бы исправить, изменив порядок действий в цикле и уменьшив K после завершения цикла, но эти действия не разрешены по условию задачи.
Поэтому для исправления ошибки можно просто скорректировать значение при выводе.
Строка с ошибкой:
write(k);
Правильная строка:
write(k-2);
Спасибо за то, что пользуйтесь нашими материалами.
Информация на странице «Задача №24. Исправление ошибок в программе.» подготовлена нашими редакторами специально, чтобы помочь вам в освоении предмета и подготовке к ЕГЭ и ОГЭ.
Чтобы успешно сдать нужные и поступить в высшее учебное заведение или техникум нужно использовать все инструменты: учеба, контрольные, олимпиады, онлайн-лекции, видеоуроки, сборники заданий.
Также вы можете воспользоваться другими статьями из разделов нашего сайта.
Публикация обновлена:
07.06.2023