Получение двойной точности в Fortran 90 с помощью компилятора Intel 11.1 - PullRequest
3 голосов
/ 10 марта 2011

У меня очень большой код, который устанавливает итеративно решает систему нелинейных уравнений в частных производных, написанную на фортране.Мне нужно, чтобы все переменные были двойной точности.В дополнительном модуле, который я написал для кода, я объявляю все переменные как тип с двойной точностью, но мой модуль все еще использует переменные из старого исходного кода, которые объявлены как тип real.Итак, мой вопрос: что происходит, когда переменная одинарной точности умножается на переменную двойной точности в Фортране?Является ли результат двойной точностью, если переменная, используемая для хранения значения, объявлена ​​как двойная точность?А что, если значение двойной точности умножается на константу без "D0" в конце?Могу ли я просто установить опцию компилятора в Intel 11.1, чтобы все реальные / двойная точность / константы двойной точности?

Ответы [ 4 ]

4 голосов
/ 11 марта 2011

Итак, мой вопрос: что произойдет, когда переменная одинарной точности умножается на переменную двойной точности в Фортране? Единственная точность повышается до двойной точности, а операция выполняется с двойной точностью.

Является ли результат двойной точностью, если переменная, используемая для хранения значения, объявлена ​​как двойная точность? Не обязательно.Правая часть - это выражение, которое не «знает» о точности переменной в левой части, в которой она будет сохранена.Если у вас есть Double = SingleA * SingleB (используя имена для обозначения типов), вычисление будет выполнено с одинарной точностью, а затем преобразовано в double для хранения.Это НЕ даст дополнительной точности для расчета!

А что, если значение двойной точности умножается на константу без "D0" в конце? Это похоже на первый вопрос, константа будет повышена до двойной точности, а вычисление выполнено с двойной точностью. Однако , константа по-прежнему имеет одинарную точность, и даже если вы записали много цифр, как для константы двойной точности, внутреннее хранилище имеет одинарную точность и не может представлять эту точность.Например, DoubleVar * 3.14159265359 будет рассчитан с двойной точностью, но это будет что-то приближенное DoubleVar * 3.14159, выполненное с двойной точностью.

Если вы хотите, чтобы компилятор сохранял много цифр в константе, вы должны указать точность константы.В Fortran 90 способ сделать это состоит в том, чтобы определить собственный реальный тип с той точностью, которая вам нужна, например, требовать не менее 14 десятичных цифр:

integer, parameter :: DoubleReal_K = selected_real_kind (14)
real (DoubleReal_K) :: A
A = 5.0_DoubleReal_K
A = A * 3.14159265359_DoubleReal_K
3 голосов
/ 10 марта 2011

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

(вещественная переменная) + (двойная переменная) -> (двойная)

(двойная переменная) * (вещественная переменная) -> (двойная)

(двойнаяпеременная) * (действительная константа) -> (double)

и т. д.

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

Если есть какие-либо случаи, когда вы обеспокоены тем, что переменная с плавающей запятой одинарной точности вызывает проблемы, вы можете принудительно преобразовать ее в двойную точность, используя встроенную функцию DBLE ():

DBLE (действительная переменная) -> double

2 голосов
/ 02 ноября 2012

Если вы напишите числа в форме 0.1D0, это будет восприниматься как число с двойной точностью, иначе, если вы напишите 0.1, точность при преобразовании будет потеряна. Вот пример:

program main
implicit none
real(8) a,b,c
a=0.2D0
b=0.2
c=0.1*a
print *,a,b,c
end program

При компиляции с

ifort main.f90

Я получаю результаты:

0.200000000000000       0.200000002980232       2.000000029802322E-002

При компиляции с

ifort -r8 main.f90

Я получаю результаты:

0.200000000000000       0.200000000000000       2.000000000000000E-002

Если вы используете компилятор IBM XLF, эквивалентность будет

xlf -qautodbl=dbl4 main.f90
1 голос
/ 10 марта 2011

Ответ Джонатана Дурси правильный - другая часть вашего вопроса была, если бы был способ сделать все реальные переменные двойной точности.

Это можно сделать с помощью компилятора ifort, используя параметры -i8 (для целых чисел) и -r8 (для действительных чисел). Я не уверен, есть ли способ заставить компилятор интерпретировать литералы с двойной точностью без указания их как таковых (например, путем изменения 3.14159265359 на 3.14159265359D0) - мы столкнулись с этой проблемой некоторое время назад.

...