Как найти ошибки в алгоритме

Введение

В данной статье рассказывается о простом алгоритме поиска ошибок в коде MQL. Часто после написания
программы возникают проблемы при компиляции, вызванные ошибками в коде. Это
могут быть самые различные ошибки, но в любом случае возникает необходимость
оперативного обнаружения участка кода, где допущена ошибка.

Нередко у людей уходит немало времени и масса нервов на поиски какой-нибудь
лишней скобки. Однако есть способ быстрого обнаружения ошибок, который основан
на использовании комментирования. Об этом методе я и расскажу в данной статье.

Концепция

Написать достаточно большой код без единой ошибки – весьма приятно. Но, к
сожалению, так выходит не всегда. Есть даже шутка, что ни одна программа не
была написана без единой ошибки. Я не рассматриваю здесь ошибки, которые
приводят к неверному исполнению кода. Здесь пойдёт речь об ошибках, из-за
которых становится невозможной компиляция.

Весьма распространённые ошибки – вставка лишней скобки в сложном условии,
нехватка скобки, не выставление двоеточия, запятой (при объявлении переменных)
и т.д. Часто при компиляции мы можем сразу увидеть, в какой строке допущена
подобная ошибка. Но бывают и случаи, когда найти такую ошибку не так просто. Ни
компилятор, ни зоркий глаз нам не могут помочь сходу найти ошибку. В
таких случаях, как правило, начинающие (и не очень) программисты начинают
«обходить» весь код, пытаясь визуально определить ошибку. И снова, и
снова, пока нервы не иссякнут, и не будет сказано «проще заново написать!».

Однако MQL, как и
другие языки программирования, предлагает потрясающий инструмент –
комментирование. Используя его можно «убирать», «отключать»
какие-то участки кода. Обычно комментирование используют именно для вставки
каких-то комментариев, или же отключения неиспользуемых участков кода. Комментирование
можно также успешно применять и при поиске ошибок.

Алгоритм поиска ошибок

Поиск ошибок обычно сводится к определению участка кода, где допущена
ошибка, а затем, в этом участке, визуально находится ошибка. Думаю, вряд ли кто-то
будет сомневаться в том, что исследовать «на глаз» 5-10 строчек кода
проще и быстрей, чем 100-500.

При использовании комментирования задача предельно проста. Сначала
нужно закомментировать различные участки кода (иногда чуть ли не весь код), тем
самым «отключив» его. Затем, по очереди комментирование снимается с
этих участков кода. После очередного снятия комментирования совершается
попытка компиляции. Если компиляция прошла успешно – ошибка не в этом участке
кода. Затем открывается следующий участок кода и т.д. Когда находится проблемный
участок кода, визуально ищется ошибка, затем устраняется. Опять происходит попытка
компиляции. Если всё прошло успешно, — ошибка устранена.

В случае возникновения новых ошибок, процедура повторяется до
их устранения. Данный подход очень полезен при написании достаточно больших программ,
но и нередко оправдывает себя и при написании относительно небольших кодов.

Весьма важно правильно определять участки кода, которые необходимо
комментировать. Если это условие (или иная логическая конструкция) – то оно
должно комментироваться полно. Если комментируется участок кода, где
объявляются переменные, важно, чтобы не был открыт участок, где происходит
обращение к этим переменным. Иначе говоря, комментирование должно применяться
по логике программирования. Несоблюдения такого подхода приводит к
возникновению новых, вводящих в заблуждение, ошибок при компиляции.

Пример

Приведу пример практического поиска ошибки в коде. Допустим, у нас есть некоторый код:

#property copyright ""
#property link      ""
 
extern int Level1=6;
extern int Level2=2;
 
extern double Lots=0.1;
extern int TP=7;
extern int SL=5000;
extern int Profit_stop=10;
 
int start()
  {


   int pos_sell=0;
 for (int i_op_sell=OrdersTotal()-1; i_op_sell>=0; i_op_sell--) 
 { 
  if (!OrderSelect(i_op_sell,SELECT_BY_POS,MODE_TRADES)) break; 
  if (Symbol()==OrderSymbol()&&(OrderType()==OP_SELLSTOP||OrderType()==OP_SELL)&&(OrderComment()=="sar_ao"))
  {
   pos_sell=1;  break;   
  } 
 }
    
   int pos_buy=0;
 for (int i_op_buy=OrdersTotal()-1; i_op_buy>=0; i_op_buy--) 
 { 
  if (!OrderSelect(i_op_buy,SELECT_BY_POS,MODE_TRADES)) break; 
  if (Symbol()==OrderSymbol()&&(OrderType()==OP_BUYSTOP||OrderType()==OP_BUY)&&(OrderComment()=="sar_ao"))
  {
   pos_buy=1;  break;   
  } 
 }
     


 


  double stop_open; 
  for (int ia=OrdersTotal()-1; ia>=0; ia--) 
  { 
   if (!OrderSelect(ia,SELECT_BY_POS,MODE_TRADES)) break; 
   if ((OrderType()==OP_BUY)&&(Symbol()==OrderSymbol())&&(OrderComment()=="sar_ao"))
   { 
    stop_open=OrderOpenPrice(); 
    if (NormalizeDouble(Bid,Digits)-stop_open<=Profit_stop*Point) continue; 
    OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()+1*Point,OrderTakeProfit(),OrderExpiration(),CLR_NONE);  
   } 
 if ((OrderType()==OP_SELL)&&(Symbol()==OrderSymbol())&&(OrderComment()=="sar_ao"))
   { 
    stop_open=OrderOpenPrice(); 
    if (stop_open-NormalizeDouble(Ask,Digits)<=Profit_stop*Point) continue; 
    OrderModify(OrderTicket(),OrderOpenPrice(),OrderOpenPrice()-1*Point,OrderTakeProfit(),OrderExpiration(),CLR_NONE);       
   } 
  }   


   int i;   
   bool trend_UP=true,trend_DOWN=true;   

if(!pos_buy)
 {  
  for(i=Level1; i>=0; i--)
   {
   
    if(Open[i]<iSAR(NULL,0,0.02,0.1,i))
    {
     trend_UP=false; break;
    }
    
   }
 
   for(i=Level2*2; i>=0; i--)
   {    
   
    if(i>Level2)
    {
     if(iAO(NULL, 0, i+1)<=iAO(NULL, 0, i))    
     { 
      trend_UP=false; break;
     }
    }
    
    if(i<Level2)
    {
     if(iAO(NULL, 0, i+1)>=iAO(NULL, 0, i))   
     {  
      trend_UP=false; break;
     }
    }          
   
   } 
 }
 else
 {
  trend_UP=false; 
 }

if(!pos_sell)
 { 
   for(i=Level1; i>=0; i--)
  {
   {
    if(Open[i]>iSAR(NULL,0,0.02,0.1,i))
    {
     trend_DOWN=false; break;
    }
    
   }
 
   for(i=Level2*2; i>=0; i--)
   { 
          
    if(i>Level2)
    {
     if(iAO(NULL, 0, i+1)>=iAO(NULL, 0, i))   
     {  
      trend_DOWN=false; break;
     }   
    }
    
    if(i<Level2)
    {
     if(iAO(NULL, 0, i+1)<=iAO(NULL, 0, i))    
     { 
      trend_DOWN=false; break;
     } 
    } 
       
   }
   
 }
  else
 {
  trend_DOWN=false; 
 }  
 
 
  if(Open[0]>iSAR(NULL,0,0.02,0.2,0))
  {
    ObjectDelete("sell"); 
  }
  
  if(Open[0]<iSAR(NULL,0,0.02,0.2,0))
  {
    ObjectDelete("buy"); 
  } 
   
double MA_1;
MA_1=iStochastic(NULL,0,5,3,3,MODE_SMA,0,MODE_SIGNAL,0);  
   if(trend_UP && MA_1<50 && Open[1]<Close[1] && !pos_buy && ObjectFind("buy") != 0)
   {   
     OrderSend(Symbol(),OP_BUY, Lots,Ask,2,Ask-SL*Point,Ask+TP*Point,"sar_ao",0,0,Blue); 
      
     ObjectCreate("buy", OBJ_ARROW, 0, Time[0], Bid);
     ObjectSet("buy", OBJPROP_STYLE, STYLE_DOT);
     ObjectSet("buy", OBJPROP_ARROWCODE, SYMBOL_ARROWUP);
     ObjectSet("buy", OBJPROP_COLOR, LightSeaGreen);
   }
   
   if(trend_DOWN && MA_1>50 && Open[1]>Close[1] && !pos_sell && ObjectFind("sell") != 0) 
   {   
      OrderSend(Symbol(),OP_SELL, Lots,Bid,2,Bid+SL*Point,Bid-TP*Point,"sar_ao",0,0,Red);   
      
      ObjectCreate("sell", OBJ_ARROW, 0, Time[0], Bid);
      ObjectSet("sell", OBJPROP_STYLE, STYLE_DOT);
      ObjectSet("sell", OBJPROP_ARROWCODE, SYMBOL_ARROWDOWN);
      ObjectSet("sell", OBJPROP_COLOR, Red);  
   }
   
 


   return(0);
  }

При попытке его компиляции мы видим сообщение об ошибке:

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

#property copyright ""
#property link      ""
 
extern int Level1=6;
extern int Level2=2;
 
extern double Lots=0.1;
extern int TP=7;
extern int SL=5000;
extern int Profit_stop=10;
 
int start()
  {
  
 

 
 


 

 
  
double MA_1;
MA_1=iStochastic(NULL,0,5,3,3,MODE_SMA,0,MODE_SIGNAL,0); 
 

  
  


   return(0);
  }

Легко можно убедиться, что такой код компилируется без проблем. Значит, участок кода, где допущена ошибка «скрыт». По очереди открываем участки кода /* … */, пытаемся откомпилировать.

Компиляция будет происходить благополучно, пока мы не дойдём до участка кода:

 
 
if(!pos_sell)
 { 
   for(i=Level1; i>=0; i--)
  {
   {
    if(Open[i]>iSAR(NULL,0,0.02,0.1,i))
    {
     trend_DOWN=false; break;
    }
    
   }
 
   for(i=Level2*2; i>=0; i--)
   { 
          
    if(i>Level2)
    {
     if(iAO(NULL, 0, i+1)>=iAO(NULL, 0, i))   
     {  
      trend_DOWN=false; break;
     }   
    }
    
    if(i<Level2)
    {
     if(iAO(NULL, 0, i+1)<=iAO(NULL, 0, i))    
     { 
      trend_DOWN=false; break;
     } 
    } 
       
   }
   
 }
  else
 {
  trend_DOWN=false; 
 }

Следовательно, ошибка именно в этой логической конструкции. При детальном «осмотре» данного участка кода, можно увидеть, что поставлена лишняя фигурная скобка в данной конструкции:

   for(i=Level1; i>=0; i--)
  {
   {
    if(Open[i]>iSAR(NULL,0,0.02,0.1,i))
    {
     trend_DOWN=false; break;
    }
    
   }

Если убрать её, код благополучно откомпилируется.

Убрав оставшиеся комментарии, мы убедимся в том, что других ошибок в коде нет. Значит, цель достигнута — ошибка в коде была найдена достаточно оперативно.

Заключение

На практическом примере было показано, как именно используется данный алгоритм
поиска ошибок. В данном примере используется весьма немаленький код (194 строки),
и на его «обход» могло бы уйти достаточно много времени. Именно
возможность комментирования экономит достаточно много времени у многих
программистов, которые сталкиваются с задачей поиска ошибок.

Предупреждение: все права на данные материалы принадлежат MetaQuotes Ltd. Полная или частичная перепечатка запрещена.

Способы поиска ошибок

Как выявлять ошибки в алгоритме

Выявление ошибок в алгоритме возможно при помощи двух способов:

1. Использование ParamDebug

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

Рисунок 1 – Отладочная таблица

Например, выведем значения индикатора «Полосы Боллинджера» для проверки в отладочную таблицу. При наведении на какой-либо бар, в таблице выведется текущее значение индикатора на этом баре.

Рисунок 2 – Проверка значений через ParamDebug

Также, чтобы убедиться в правильности расчетов, значения в отладочной таблице данного индикатора можно сравнить со значениями готового индикатора (при его наличии) в TradingView.

Если в итоге значения с ParamDebug не сходятся, то можно в TradingView посмотреть код данного индикатора, разбить его на части и выводить промежуточные значения в TradingView. (Рисунок 4)

Процесс проверки:
1. Открываем код индикатора и делаем его копию, чтобы появилась возможность его редактировать.

Рисунок 5 – Копия кода индикатора

2. Изменяем код, например, хотим проверить значения переменной «dev» с нашим значением в ParamDebug. Значения «dev» выводится с помощью функции plot, как показано на рисунке ниже.

Рисунок 6 – Вывод значений

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

Это один из вариантов проверки. Также можно сравнить значения с помощью Excel таблицы, если ТЗ в таблице и есть форма расчетов для проверки, например для расчета индикатора «Коэффициента корреляции» (рисунок 7).

Рисунок 7 – Проверка значений через Excel таблицу

Процесс проверки через Excel таблицу:

  1. Открываем график двух инструментов, например (BTCUSDT и BNBUSDT);
  2. Подставляем значения закрытой свечи (кол-во зависит от периода расчета) этих двух инструментов в таблицу;
  3. Сверяем значения 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:

  1. Покрыть код ParamDebug, где требуется проверить правильность работы алгоритма
  2. Сравнить значения с TradingView (при наличии существующего скрипта) и разбить код на части, выводить промежуточные значения
  3. Использовать Excel (если есть расчеты)
  4. Debug в Visual Studio

Пример поиска ошибка через ParamDebug или отладки в Visual Studio:

Данное покрытие кода позволяет просмотреть разные участки кода, которые будут выполняться. Если на отладочной таблице в ETS будет видно, к примеру, ParamDebug(«Test», 1) и не видно ParamDebug(«Test», 2), это означает, что номер бара меньше указанного значения. Таким способом, покрывая ParamDebug можно идти в глубину кода и просматривать, в какие моменты код срабатывает или нет.

Check List ParamDebug/отладка в Visual Studio:

  1. Покрыть те участки кода, где необходимо посмотреть исполнения кода;
  2. Если выполняется код до функции, но функция пропускается, то углубляться в данную функцию и покрывать ее ParamDebug;
  3. Также углублять в подфункции (при наличии);
  4. Просматривать значения переменных, при которых не выполняется код;
  5. Сравнивать значения выше указанными способами (Excel, TradingView).

Check List Excel:

  1. Заполнять таблицу необходимыми значениями при расчетах;
  2. Разбивать формулу расчета на части;
  3. Сверять значения каждой части формулы с полученными.

Check List TradingView (при наличии готового кода):

  1. Найти индикатор;
  2. Скопировать скрипт, чтобы в дальнейшем изменять;
  3. Разбить алгоритм на части;
  4. Выводить промежуточные значения на график и сверять со своими промежуточными.

Все возможности открывает платформа 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);
?>

Далее мы анализируем каждый вывод переменной:

  1. Так, переменная x выдала значение 5. Следовательно, эта переменная передалась верно.
  2. Переменная y имеет значение 4, что так же верно, ведь именно 4 мы и передавали.
  3. И, наконец, переменная 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.

Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновления

Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.

Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):

  1. Кнопка:

    Она выглядит вот так: Как создать свой сайт

  2. Текстовая ссылка:

    Она выглядит вот так: Как создать свой сайт

  3. 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)

Получив приказ
исполнить алгоритм, компьютер выполняет
следующие действия:

  1. Находит в памяти
    алгоритм с указанным именем.

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

  3. Последовательно
    читает команды после строки нач
    и передает
    их исполнителю. Каждый такой приказ на
    выполнение команды называется вызовом
    этой команды.

  4. Встретив строку
    кон,
    проверяет,
    достигнута ли цель алгоритма, указанная
    в строке надо
    (см. примечание
    к п. 2).

  5. Заканчивает
    выполнение алгоритма.

Пример.
Компьютер
получает приказ исполнить алгоритм
«ход конем».

  1. Компьютер находит
    в памяти алгоритм А1.

  2. В строке дано
    записан
    комментарий — компьютер его пропускает.

  3. Компьютер
    последовательно командует Роботу
    вправо,
    вправо, вниз
    .
    Робот
    исполняет
    эти команды.

  4. В строке надо
    помещен
    комментарий — компьютер его пропускает.

  5. Компьютер
    заканчивает выполнение алгоритма «ход
    конем».

7.6. Ошибки в алгоритмах

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

Но даже если все
команды записаны правильно, это еще не
значит, что алгоритм составлен без
ошибок. Ошибки в составлении алгоритма
называются логическими.

Иногда логическая
ошибка может привести к отказу
— невозможности
выполнить очередную команду. Например,
при попытке выполнить алгоритм «ход
конем» (А1) в обстановке, изображенной
на рисунке 2, компьютер попытается
последовательно вызвать команды вправо,
вправо, вниз
.
Однако вторую команду вправо
Робот выполнить
не сможет — возникает отказ. Получив
от исполнителя сигнал отказа, компьютер
сообщает об ошибке и прекращает выполнение
алгоритма.

Рис. 2

У каждого исполнителя
могут быть свои причины отказов. Отказ
Робота
возникает
при попытке идти сквозь стену.

Ошибки в алгоритме
не всегда приводят к отказам. Возможны
логические ошибки, не обнаруживаемые
компьютером ни до, ни во время выполнения
алгоритма. Так, если в алгоритме А1 мы
вместо вправо
случайно напишем влево,
то компьютер выполнит алгоритм, Робот
из клетки А
переместится в клетку В (см. рис. 2), но
никаких сообщений об ошибках мы не
получим (да и откуда компьютеру знать,
куда мы на самом деле хотели переместить
Робота!).

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

Таблица 1. Ошибки
в алгоритмах.

Смысл ошибки

Название

Пример

1

Цель не достигнута

Логическая

Робот не попал
куда надо

2

Команда не входит
в СКИ

Синтаксическая

наверх, направо

3

Авария при попытке
исполнения команды

Семантическая
(отказ)

Попытка пройти
сквозь стену

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]

  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #

Понравилась статья? Поделить с друзьями:
  • Как найти произведение координат вектора формула
  • Как найти океан в террарии
  • Как найти диагонали пятиугольника
  • Как найти деревню по сети
  • Los роутер как исправить