Хобрук: Ваш путь к мастерству в программировании

Правило Симпсона, объявление запрошенного пользователем ввода не принято? фортран

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

Я понимаю, что мог бы сделать пи параметром в основной части программы, но я бы предпочел просто выяснить, где я ошибаюсь. Любая помощь будет очень высоко ценится.

module consts

        !Declare pi as a global variable 
     real(4),parameter :: pi=3.1415927
end module


PROGRAM simpson
  use consts
  implicit none
  REAL :: area, h, sumo, sume
  INTEGER (kind=4) :: i, j, k !Loop index, Counter, Number of points
  REAL (kind=4) ::  rad, TanTab(0) !Radian variable to be calculated in Subroutine, Result array
!k = number of steps
   WRITE(6,*) "Please enter number of steps required (odd number)"
   READ(5,*) k

    IF(MOD(k,2) ==  1) THEN

CONTINUE
    ELSE
WRITE(*,*) "Hey, I said as an odd number"
    READ(5,*) k

    ENDIF


h = (60.0)/(k-1) ! Defining step size in relation to number of sampling points

 DO i=1,61,1
! Get table of tan
     call degtorad((i-1)*1.0, rad)

     TanTab(j) = tan(rad)

     j=j+1
    write(*,*) "Tan(", i, ")", TanTab(i)
    write(*,*) "Tan(", j, ")", TanTab(j)
 ENDDO

  DO j=1,k-1,h 
    IF(MOD(k,2) == 1) THEN
    sumo = sumo + TanTab(j)  !sum of odd functions
    ELSE
    sume = sume + TanTab(j)   !sum of even functions

    area = (h/3)*( (4*sumo) + (2*sume) + tan(1.047))
WRITE(6,*) area
    ENDIF
  ENDDO





END PROGRAM simpson

  • Какие ошибки вы получаете? 18.02.2014
  • Ваш размер шага h равен real! Это может привести к огромным (и трудно обнаруживаемым) ошибкам. Пожалуйста, используйте только integers для счетчиков циклов... Также позаботьтесь о смешивании reals и integers (как в h = (60.0)/(k-1)) - это может вести себя не так, как вы предполагали. 18.02.2014
  • Вы сами это написали или это домашняя работа по поиску ошибок? Среди многих проблем ваша окончательная запись никогда не будет обнаружена, потому что она находится внутри конструкции if k even, а наверху вы (вроде как пытаетесь) убедиться, что k нечетно. Также почему жесткий код 61 в первом цикле? 18.02.2014
  • Привет Джордж, я написал это сам - просто решая некоторые задачи в книге, поэтому я использовал некоторые фрагменты кода, которые я написал в других задачах. Очевидно, мне еще многое предстоит узнать о смешивании переменных, и я делаю простые ошибки, такие как запись 1 вместо 1.0 при попытке использовать и работать с реальными. Теперь я усвоил урок об использовании вещественных чисел в циклах. Может ли кто-нибудь порекомендовать хороший отладчик для фортрана? Я получаю информацию об ошибках на уровне исходного кода от моего компилятора Intel, но должно быть что-то более существенное? 19.02.2014

Ответы:


1

У вас больше ошибок в коде:

  • при расчете h вы используете градусы, а не рад
  • верхняя граница интеграла, связанная с количеством элементов в массиве TanTab
  • не инициализировать переменные в 0 (sumo, sume,...)
  • расчет площади для каждого шага может быть выполнен вне цикла do
  • ошибки за пределами поля

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

  PROGRAM simpson
  implicit none
  REAL :: area, h, sumo, sume
  INTEGER (kind=4) :: i!Loop index
  integer, parameter :: k = 100
  REAL (kind=4) ::  rad, TanTab(k+1) !Radian variable to be calculated in Subroutine, Result array

  sumo = 0.0
  sume = 0.0
  area = 0.0
  h = 0.0174532925 * 60.0/real(k) ! Defining step size in relation to number of sampling points

  DO i=1,k+1
      rad = 0.0174532925 * 60.0 * real(i-1) /real(k)
      TanTab(i) = tan(rad)
      ! write(*,*) "Tan(", i-1, ")", TanTab(i)
  ENDDO

  DO i=2,k
      IF(MOD(i,2) == 1) THEN
        sumo = sumo + TanTab(i)  !sum of odd functions
      ELSE
        sume = sume + TanTab(i)  !sum of even functions
      ENDIF
  ENDDO

  ! by simson
  area = (h/3)*( TanTab(1) + (2*sume) + (4*sumo) + TanTab(k+1))
  WRITE(*,*) area

  ! by integration
  area = log(1.0) - log(cos(0.0174532925 * 60.0))
  WRITE(*,*) area
  END PROGRAM simpson
18.02.2014
  • Если вы собираетесь опубликовать рабочую версию, почему бы не опубликовать хорошую? Выбор нит (i) log(1.0) всегда 0, так зачем беспокоиться (ii) вы объявили k реальным, затем пару раз применили его ( real(k) ) и обычно использовали его, как если бы это были integer (iii) константы, такие как 0.0174532925 * 60.0 являются хорошими кандидатами для объявления в качестве параметров. Возможно и другие проблемы. 18.02.2014
  • Код работает с точки зрения того, что вы получаете разумное приближение интеграла, и он четко показывает все ошибки, которые были в исходном вопросе. К вашему комментарию i) Это не производственный код, но показывает математику. Даже log(1.0) равен 0, это более понятно с точки зрения того, что там происходит ii) я объявил k как int (как в вопросе) и забыл, что позже я изменил это значение на real iii) то же, что и i) он явно показывает преобразование градусов в рад, что лучше для понимания кода. 18.02.2014
  • Приятно иметь сравнение между реализацией по правилу Симпсона и интеграцией для понимания. Хорошая новость заключается в том, что я понимаю, что вы написали, и это должно помочь мне избежать повторения простых ошибок. 19.02.2014
  • @ user3311029 Я рад, что это помогло. Помните, когда вы пишете новый код, всегда приятно найти способ проверить, правильно ли код выполняет свою работу (это называется тестированием). 19.02.2014

  • 2

    Я вижу одну вероятную причину сбоя во время выполнения, вызывающую нарушение сегментации:

    Вы используете j в строке

     TanTab(j) = tan(rad)
    

    прежде чем присвоить ему значение. Фортран не выполняет автоматической инициализации переменных.

    Я также вижу что-то очень подозрительное. Вы объявляете, что tantab имеет измерение 0:

     REAL (kind=4) ::  rad, TanTab(0)
    

    Теперь Фортран с радостью будет обращаться к элементам массивов за пределами их объявленных границ и иногда (иногда очень долго) пользователи программы не замечают проблемы. Если вы скомпилируете свой код с параметром -check bounds (это версия Intel, другие компиляторы имеют такие же возможности, обратитесь к документации), а затем попытаетесь запустить свой код, вы должны получить ошибку времени выполнения.

    И я согласен с @AlexanderVogt (обычно я согласен) в том, что вы используете реальную переменную для индекса цикла. Не делай этого.

    18.02.2014
  • Спасибо, вместо этого я объявил, что он имеет размерность 1, и присвоил значение j перед циклом do, но теперь, несмотря на то, что он компилируется, он не печатает никаких результатов после того, как я ввожу нечетное число для ввода? 18.02.2014
  • Давать TanTab размерность 1 так же неправильно, как давать ему размерность 0, когда из вашего кода ясно, что вы хотите создать таблицу значений касательных. Почему вы не объявляете, что массив имеет правильный размер или размер, который можно установить во время выполнения? Я больше не буду комментировать. Если вы хотите получить дополнительную информацию, отредактируйте свой вопрос, чтобы отразить обновленные проблемы. И, ради Кнута, сообщите нам, какие именно сообщения об ошибках или ненормальное поведение вы испытываете. 18.02.2014
  • Грандиозно, он больше не выдает никаких ошибок, он просто завершает работу во время работы после запроса ввода и разрешения мне ввести его, как только что было сказано. Я запутался в понятии размеров, я пробую 2 для таблицы, я пробую 62 для количества шагов - каждый раз одна и та же проблема. Мне не нужно делать это ни для чего, кроме моего собственного обучения, так что не беспокойтесь и спасибо за ваше время. 18.02.2014

  • 3

    Некоторые вещи, о которых следует подумать: Цикл DO i=1,61,1 предполагает, что вы должны установить TanTab(i), а не TanTab(j). Зачем возиться с дополнительной переменной j, которая увеличивается так же, как i? И поскольку цикл идет от 1 до 61, предполагается, что вы должны объявить TanTab как real, dimension (1:61) :: TabTab, иначе он не будет достаточно большим для хранения значений. Но тогда ваш следующий цикл, DO j=1,k-1,h, будет другим. Вы уверены, что он последовательно обращается к TabTab (j)?

    18.02.2014
  • Ах, мне не приходило в голову, что использование 'j' было излишним, потому что я частично переводил старый код, написанный на C для аналогичной задачи. 19.02.2014
  • Новые материалы

    Создание кнопочного меню с использованием HTML, CSS и JavaScript
    Вы будете создавать кнопочное меню, которое имеет состояние наведения, а также позволяет вам выбирать кнопку при нажатии на нее. Финальный проект можно увидеть в этом Codepen . Шаг 1..

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

    Классы в JavaScript
    class является образцом java Script Object. Конструкция «class» позволяет определять классы на основе прототипов с чистым, красивым синтаксисом. // define class Human class Human {..

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

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

    Обзор: Машинное обучение: классификация
    Только что закончил третий курс курса 4 часть специализации по машинному обучению . Как и второй курс, он был посвящен низкоуровневой работе алгоритмов машинного обучения. Что касается..

    Разработка расширений Qlik Sense с qExt
    Использование современных инструментов веб-разработки для разработки крутых расширений Вы когда-нибудь хотели кнопку для установки переменной в приложении Qlik Sense? Когда-нибудь просили..