Фортран: возможное изменение значения

У меня есть код fortran, скомпилированный в gfortran (несколько тысяч строк, поэтому я постараюсь опубликовать важные строки), который дает мне:

nrev(isat)=dint((t_ref-t_in)/zper)+1
           1
Warning:Possible change of value in conversion from REAL(8) to INTEGER(4) at (1)

Они инициализируются как:

integer*4  nrev(nmaxsat)
integer*4  isat
real*8     t_ref
real*8     t_in
real*8     zper

Есть какие нибудь идеи как это починить? Спасибо!


person Astro_21    schedule 09.04.2012    source источник
comment
Что именно вы хотите исправить? В зависимости от величины выражения двойной точности оно не будет представлено как 32-битное целое число со знаком. Чего вы ожидаете?   -  person talonmies    schedule 09.04.2012
comment
Когда я запускаю полную программу, все выходные значения являются NaN, поэтому я обеспокоен такими предупреждениями. У меня нет ошибок при компиляции в gfortran, однако при компиляции в g77 он компилируется и работает корректно. У меня есть несколько таких предупреждений, но я сосредоточился на этом, надеясь, что если мне помогут с одним, я смогу выяснить остальные.   -  person Astro_21    schedule 09.04.2012
comment
Если вы получаете значения NaN, это означает, что где-то у вас есть недопустимое вычисление с плавающей запятой. Код, который вы показали, вычисляет целочисленное значение. Невозможно сказать, как они могут быть связаны, основываясь на том, что вы опубликовали.   -  person talonmies    schedule 09.04.2012
comment
Я новичок в программировании и совершенно не знаком с Фортраном... что вы подразумеваете под недопустимой плавающей запятой? Может ли это быть вызвано изменением версии с g77 на gfortran? И пока я думаю об этом, знаете ли вы, в чем разница между Возможным изменением значения при преобразовании и несоответствием типов в предупреждениях аргументов? Кажется, они говорят одно и то же двумя разными способами... Еще раз спасибо!   -  person Astro_21    schedule 09.04.2012
comment
Недопустимая означает операцию, которая не может быть представлена ​​как действительное число в диапазоне используемого вами типа с плавающей запятой. Обычными виновниками являются деление на ноль, извлечение логарифма или квадратного корня из отрицательного действительного значения. Другой возможностью является использование значения без присвоения ему значения. Некоторые компиляторы автоматически обнуляют значения, другие — нет. Стандарт не определяет, требуется ли неявная инициализация значений или нет.   -  person talonmies    schedule 09.04.2012
comment
Проведя небольшое исследование, похоже, что возможное добавление неявного none перед обозначением переменной может помочь убедиться, что этого не произойдет. Есть ли такая большая разница между компиляторами g77 и gfortran, что gfortran будет иметь неверную математику, в то время как g77 в порядке?   -  person Astro_21    schedule 10.04.2012


Ответы (1)


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

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

Если вы хотите выполнить преобразование, а также усечение, idint фактически преобразуется в целое число.

Так, например, эта программа

program foo

    integer :: nrev
    double precision :: t_ref

    t_ref  = 1.

    nrev = dint(t_ref)

end program foo

создает такое же предупреждение:

$ gfortran -o foo foo.f90 -Wall -std=f95
foo.f90:8.11:

    nrev = dint(t_ref)
           1
Warning: Possible change of value in conversion from REAL(8) to INTEGER(4) at (1)

Но этот хорош:

program foo

    integer :: nrev
    double precision :: t_ref

    t_ref  = 1.

    nrev = idint(t_ref)

end program foo

как мы видим:

$ gfortran -o foo foo.f90 -Wall -std=f95
$ 
person Jonathan Dursi    schedule 09.04.2012
comment
Вместо использования определенного встроенного идентификатора вы можете использовать общее имя int. С универсальным компилятор автоматически определяет, какую функцию использовать, исходя из типа аргумента, и программисту не нужно запоминать имя. (Также есть второй аргумент, в котором вы можете указать тип целого числа, возвращаемого функцией.) - person M. S. B.; 10.04.2012
comment
Большое спасибо за это объяснение! Это поможет мне значительно очистить этот код и заставить его работать намного лучше. Я спросил об этом в комментарии выше, но можете ли вы объяснить, в чем разница между возможным изменением значения при преобразовании и несоответствием типов в предупреждениях аргументов? Мне кажется, они говорят одно и то же двумя разными способами... Еще раз спасибо! - person Astro_21; 10.04.2012