Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Fortran > [General] Ошибка времени исполнения


Автор: ghost8495 1.4.2009, 21:14
Задали написать програму на Фортране, но не удаётся запустить  exe файл. помогите найти ошибку
вот условие задачи:
для каждого из значений переменно  С, равных 0.8,  0.9,  1.0,  1.1,  1.2, определить площадь S, ограниченную кривой F(x)=((x-c)**2)*((x+c)**2)  и осью абсцисс на отрезке [a, b ] . Известно, что в точке а функция F(x) принимает своё максимально на отрезке [0, c ] значание. Значение b положить равным 0.7*с . Обязательно использование подпрограмм EXLOC  И FINT







program prog1
    real c, b, s, a, e, FINT 
    integer i
    external F
    common c

    e=0.01
    c=0.8
      m=1
    i=1
    
    do while (i.le.5)
     b=0.7*c
      a=1
       s=fint(f, a, b, e)
        write(*,77) c,a,s
   77       format(1x, 'c=',F5.3, 1x, 'a=', F5.3, 1x, 's=',F5.3)
        c=c+0.1
     i=i+1
    end do
    pause
    end

    real function FINT(F, a, b, e)
    integer n, i
    real f, a, b, e, s, spread,h, x

 
      s=0
    spred=0
    n=100
    do while ((abs(s-spred).ge.e.or.n.le.2*100).and.n.le.100000)
       spred=s
       h=(b-a)/n
       s=0
       x=a
       do i=1,n
          s=s+F(x)
         x=x+n
       enddo
        s=s*h
     n=2*n
      enddo
    FINT=s
    end

    
     
     
      
    
     
     
      real function F(x)
    real x
    common c
    f=((x-c)**2)*((x+c)**2)
    end

Автор: FCM 3.4.2009, 09:24
Что значит не запускается исполняемый файл - может не строится вообще?

В определении функции F(x) по моему не хватает явного описания, ассоциированной через COMMON-блок переменной с. Добавь   real c

Автор: FatalError 3.4.2009, 14:05
Что бросилось в глаза - двойное определение FINT: сначала как real (т.е. как число!), потом - как функция. Какой уж там ехе-файл, до этого дело точно не дойдет: у компилятора от такого финта мозги на бекрень съедут! Да, требуемая в условии подпрограмма EXLOC не использована! (а может, и фиг с ней?)

Автор: FatalError 3.4.2009, 14:24
Это, конечно, не ошибка, но кто Вас учил так циклы строить??? С самодельным увеличением фактического параметра цикла? Почему нельзя позволить фортрану самому его увеличивать, используя стандартную конструкцию цикла? И если заранее известно, что циклов будет ровно пять, ни одним меньше и ни одним больше, зачем использовать конструкцию do while, потенциально опасную сваливанием в бесконечный цикл? Оно понятно, что здесь вроде не должно так зациклиться, но вдруг где ошибочка проскочит? Да, это я говорил про цикл в основной программе, вокруг метки 77. Что там делает do while в подпрограмме, это я еще не вникал. Ну и про обсуждаемый цикл должен сказать еще и пару слов одобрения: правильно, что не был сделан цикл с переменной c в качестве параметра и с ее изменением с шагом 0.1, хотя он вроде и напрашивается!

Автор: FatalError 3.4.2009, 15:09
Под описанием "финта" - функции FINT(F, a, b, e) - определяется переменная spread, а используется дальше неинициализированная переменная spred. Средство борьбы с подобными опечатками очень простое: пишем директиву implicit none в начале программы, компилятор будет ругаться на все ранее не описанные переменные.

Далее. "Финт" вроде должен считать площадь на основании входных данных. Входные данные не верные: параметр а в основной программе определяется константой (a=1), хотя это точка с интервала [0, c ], в которой функция F(x) максимальна. Так как некоторые значения переменной с меньше единицы, то точка а для них благополучно улетает за пределы заданного интервала. И зачем надо численно (по методу трапеций) считать площадь под функцией, если для этой функции известно аналитическое выражение?

Что делать? Составить нормальный алгоритм решения:

1. Надо как следует потрясти функцию F(x) и выбить из нее все нужные показания. Поскольку нас интересует интервал [0, c ], в точке 0 она всегда равна с**4, в точке с - нулю. Далее - берем ее производную и убеждаемся, что на участке [0, c[ она отрицательна. Стало быть, она монотонно падает, и ее высшая точка на этом интервале - при х=0. Стало быть, а=0, и нам надо интегрировать на участке от 0 до b = 0.7*с

2. А теперь, хе-хе, начинаем интегрировать. В общем виде. Поскольку это полином, найти первообразную - задачка для школьника. Ну и, соответственно, находим площадь как определенный интеграл, т.е. разность значений первообразной на концах отрезка. В общем виде, как полином, т.е.функцию от параметра с.

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

Автор: awers 3.4.2009, 15:12

 ! 
awers
ghost8495, пользуйтесь кнопкой "код"

Автор: ghost8495 3.4.2009, 21:15
спасибо за справедливые замечания, сижу исправляю

Автор: ghost8495 9.4.2009, 22:50
Исправил, доработал, но есть одно "но" : площадь слишком уж маленькая (

Код

program lab1
    real c, b, s, a, e
    integer i
    external F
    common c
    e=0.01
    c=0.8
      m=1
    i=1
    a=0
    do while (i.le.5)
     b=0.7*c
           a=exloc(f,a,b,e,m)
           s=fint(f, a, b, e)

        write(*,77) c,a,s
 77       format(1x, 'c=',F5.3, 1x, 'a=', F5.3, 1x, 's=',F5.3)
        c=c+0.1
     i=i+1
    end do
    pause
    end

    real function EXLOC (f,a,b,e,m)
    integer m
    real F,a,b,e,aa,bb,cc,xl,xp
    aa=a
    bb=b
    do while (bb-aa.gt.e)
    cc=(aa+bb)/2
    xl=cc-0.01*e
    xp=cc+0.01*e
    if(m*(F(xl)-F(xp)).gt.0) then
    bb=xp
    else
    aa=xl
    endif
    enddo
    EXLOC=(aa+bb)/2
    return
    end

      real function FINT(F, a, b, e)
    integer n, i
    real F, a, b, e, s, spred,h, x
    
      s=0
    spred=0
    n=100
    do while ((abs(s-spred).ge.e.or.n.le.2*100).and.n.le.100000)
       spred=s
       h=(b-a)/n
       s=0
       x=a
       do i=1,n
          s=s+F(x)
         x=x+n
       enddo
        s=s*h
     n=2*n
      enddo
    FINT=s
    
      end

    
     
     
   
    real function F
    real x, c
    common c
    f=((x-c)**2)*((x+c)**2)
    end


http://www.radikal.ru

Автор: FatalError 10.4.2009, 16:06
Скорее всего, из-за неправильного обращения с функцией F. Зачем ее повсеместно объявлять как real? Например:

real F, a, b, e, s, spred,h, x

Это значит, что F - просто дробное число. И зачем вставлять F в аргументы функции FINT?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)