перевод цикла из Fortran в MATLAB

В настоящее время я перевожу код с Fortran на MATLAB вручную и не знаю, как перевести его часть. (Весь код на самом деле представляет собой подпрограмму из 2000 строк.) Код приведен ниже.

C  Has series crossed neckline?
120        neckext=x(trough(peaknum-1))+
 *              dydx*real((t-trough(peaknum-1)))


        if(x(t).lt.neckext) goto 130
C      NO.  Here if series has not crossed neckline, nor new trough found
C           Check to see if new trough has been found.
        t=t+1
        if(t.ge.lastobs) goto 900
        if(x(t).lt.min) then
              min=x(t)
              mindate=t
              end if
        troughid=min*(1.0+cutoff)
        if(x(t).ge.troughid) goto 150
        goto 120

C      YES. Here if series crossed neckline before new trough found
130         dblcount=0
      if(poscount.ge.1) then
          DO 132 i=1,poscount
           if((enterdt(i)-2.le.t).and.(t.le.enterdt(i)+2)) then
           dblcount=dblcount+1
           end if    
132          continue
           if(dblcount.ge.1) then
C                write(30,2583) t,Cutnum
2583            format('DoubleCounting episode occurred at ',I5,
 *             ' with Cutoff = ',F3.1)
            goto 150
          end if
       end if

Моя проблема связана с этой частью кода:

        if(x(t).ge.troughid) goto 150
        goto 120

Когда я переводил эту часть в MATLAB, я писал что-то вроде:

if x(t,:)>=troughid
    t=marker;
    minimum=x(t,:);
end

Но я не знаю, что делать с лейблом 120. Когда я его переведу, я снова напишу эту часть? Потому что, насколько я понимаю, когда я вернусь к 120, код снова будет работать. Спасибо!

РЕДАКТИРОВАТЬ: В ответ на вопрос Криса о том, что делают метки 150 и 900, я опубликую их здесь.

150        t=marker
           min=x(t)

И это за лейбл 900.

C  Last observation found.  This iteration finished.
900        continue

person Julio Galvez    schedule 04.09.2012    source источник
comment
А еще говорят, что goto затрудняют понимание кода!   -  person High Performance Mark    schedule 04.09.2012
comment
@HighPerformanceMark Это правда. Это точно. С другой стороны, сколько еще языков имеют огромное количество закаленного в боях числового кода? Я полагаю, что это дань как абсолютной простоте F66/F77, так и сорока годам пролития крови, достоинства и слез аспирантов.   -  person sfstewman    schedule 04.09.2012
comment
Если вы этого не сделали, стоит разработать комплексные (и в идеале автоматизированные) тесты, чтобы убедиться, что ваш порт действительно воспроизводит исходное поведение. Такая работа утомительна и чревата ошибками. Хороший набор тестов может сэкономить огромное количество времени и нервов, особенно если этот код важен для какой-то более важной и сложной цели.   -  person sfstewman    schedule 04.09.2012
comment
Попробуйте онлайн-конвертер F77 в F90 по адресу polyhedron.com/plusfortonline.php, чтобы получить фрагменты кода. Это поможет вам разгадать goto статусы.   -  person John Alexiou    schedule 04.09.2012
comment
Привет @ ja72, я действительно думал разбить код на части и преобразовать его в F90. Но дело в том, что код настолько сложен, что его сложно разбить на части. (Поскольку я видел, что plusfort позволяет делать это только по 100 строк за раз.)   -  person Julio Galvez    schedule 06.09.2012
comment
@sfstewman Что вы имеете в виду под тестированием? :)   -  person Julio Galvez    schedule 06.09.2012


Ответы (3)


Как уже должно быть ясно, Matlab не включает никаких вариантов команды «goto». Основной набор команд Matlab, по-видимому, разработан на основе философии «структурированного программирования». (Что, если я правильно помню свою древнюю историю CS, было большим спором до объектно-ориентированного программирования.) В Википедии есть приличный обсуждение структурного программирования.

В темные дни до структурного программирования люди были в восторге от блок-схем, поскольку это был один из самых простых способов визуализировать и понять фрагмент кода с использованием множества операторов goto (сейчас их обычно называют спагетти-кодом).

Я подозреваю, что вам нужно будет составить блок-схему всей подпрограммы, а затем решить, какие конструкции потока управления лучше всего использовать для воссоздания вашего кода. Если это относительно простая диаграмма, вы сможете воссоздать весь код с помощью операторов if или операторов case, хотя ряд небольших вспомогательных функций может быть более элегантным. Если он имеет более сложную структуру, то для перевода может потребоваться немного больше творчества.

person Pursuit    schedule 04.09.2012
comment
Спасибо! Я написал блок-схему всей подпрограммы и обнаружил, что структура у нее сложная; кажется, что петли идут вперед и назад друг с другом. Однако я не уверен, как их кодировать. В любом случае, могу я спросить вас о различии между операторами if и case? Интуитивно они кажутся одинаковыми. - person Julio Galvez; 07.09.2012
comment
В Matlab оператор case в основном является сокращением для серии операторов if ... elseif ... elseif ... else ... end. В общем проще понять. - person Pursuit; 07.09.2012
comment
Спасибо! Теперь, в случае, когда некоторые циклы могут перекрываться друг с другом (так как это было в случае с результатом моей блок-схемы), какие приемы я могу использовать, чтобы распутать перекрытие? Когда я обычно использую break, return и continue? - person Julio Galvez; 07.09.2012
comment
Лично я никогда не использую break или continue. Я обеспокоен тем, что выйду на неожиданный уровень. return предназначен для раннего выхода из функции, которую вы, похоже, не используете. Что касается распутывания блок-схемы спагетти, я думаю, что это выходит за рамки того, что я могу разумно сделать. Некоторый поиск в Google блок-схем структурированного программирования дает несколько инструкций по теме, например. hancock.k12.ky.us/hchs/cisco/ программирование/pdf/. - person Pursuit; 07.09.2012
comment
Большое спасибо за это; это было намного яснее, чем руководство, которое я нашел в Интернете! - person Julio Galvez; 08.09.2012

Вы можете обернуть первую половину своего кода до тех пор, пока после goto 120 в цикле while. Затем вы можете выйти из этого цикла, когда условие if(x(t) .lt. neckext) будет выполнено. Например, логика может выглядеть примерно так. Обратите внимание, что я не пытался преобразовать все это в MATLAB (это ваша работа!!), но, надеюсь, это поможет вам начать работу.

% Has series crossed neckline?
neckext = x(trough(peaknum-1)) + dydx*real((t-trough(peaknum-1)));

if (x(t) < neckext)
    % Code below `goto 120` here...

else
    while (x(t) >= neckext)
        % Code above `goto 120` here...
    end 
end

% `goto 150` code here?

Я не совсем уверен, что это то, что вам нужно, так как без полного кода я понятия не имею, что goto 150 и goto 900 должны делать с потоком программы (кроме того, что за этим трудно следить).

person Chris    schedule 04.09.2012
comment
Привет @Chris, на самом деле я перевожу подпрограмму из 2000 строк. Во всяком случае, я опубликую, что goto 150 и goto 900 делают с ходом программы. 150 t=маркер min=x(t) 900 продолжить - person Julio Galvez; 04.09.2012

Почти все разрешенные goto в Fortran могут быть переведены в MATLAB с помощью конструкций while/break/continue. Я написал (не выпущенную) программу для автоматического удаления goto из кода Fortran, затем я использую свою программу f2matlab для перевода кода в MATLAB/Octave.

person Ben Barrowes    schedule 04.09.2012
comment
Я отредактировал вопрос, чтобы удалить ваш адрес электронной почты. См. этот мета-вопрос и связанные вопросы для получения дополнительной информации о том, почему. На этом сайте предпочтительно, чтобы ответы были автономными, а не в форме, отправьте мне электронное письмо, и я могу исправить это для вас. В будущем вы можете упомянуть свой код, но постарайтесь поставить ссылку (скажем, на github), чтобы любой, кто читает этот ответ, мог следить за решением, даже если вы покинете этот сайт или измените адрес электронной почты. - person Chris; 05.09.2012