Для проекта, над которым я работаю, я написал в C ++ очень простую функцию:
Fne(x) = 0.124*x*x
проблема в том, когда я вычисляю значение функции
за x = 3.8938458092314270
и с Фортраном 77, и с языками C ++ я получил разное преимущество.
Для Фортрана я получил Fne(x) = 1.8800923323458316
и для C ++ я получил Fne(x) = 1.8800923630725743
, Для обоих языков функция Fne кодируется для значений двойной точности и возвращает также значения двойной точности.
Код C ++:
double FNe(double X) {
double FNe_out;
FNe_out = 0.124*pow(X,2.0);
return FNe_out;
}
Код Фортрана:
real*8 function FNe(X)
implicit real*8 (a-h,o-z)
FNe = 0.124*X*X
return
end
Не могли бы вы помочь мне выяснить, откуда эта разница?
Одним из источников различий является обработка по умолчанию C ++ и Fortran литеральных констант, таких как ваша 0.124
, По умолчанию Fortran будет рассматривать это как число с плавающей запятой одинарной точности (практически на любой комбинации компьютера и компилятора, которую вы, вероятно, будете использовать), в то время как C ++ будет рассматривать его как число f-p двойной точности.
В Фортране вы можете указать kind
числа f-p (или любой другой внутренней числовой константы в этом отношении и отсутствие каких-либо опций компилятора для изменения наиболее вероятного поведения по умолчанию) путем суффикса вид-селектор как это
0.124_8
Попробуйте, посмотрите, что получится.
О, и пока я пишу, почему вы пишете на Фортране, как это было в 1977 году? И всем остальным экспертам Фортрана поблизости, да, я знаю, что *8
а также _8
это не лучшая практика, но у меня нет времени, чтобы подробно остановиться на этом.
Как отметило High Performance Mark, проблема точности литералов по умолчанию. С помощью
double xx = 3.8938458092314270;
std::cout << std::setprecision(16);
std::cout << " (float) * x*x: " << 0.124f*xx*xx << std::endl;
std::cout << "(double) * x*x: " << 0.124*xx*xx << std::endl;
Мы получаем
(float) * x*x: 1.880092332345832
(double) * x*x: 1.880092363072574
это та же самая разница, которую вы заметили.