Разная точность в C++ и Fortran

Для проекта, над которым я работаю, я написал на С++ очень простую функцию:

Fne(x) = 0.124*x*x, проблема в том, что я вычисляю значение функции

для x = 3.8938458092314270 с языками Fortran 77 и C++ я получил другую точность.

Для Fortran я получил Fne(x) = 1.8800923323458316, а для C++ я получил Fne(x) = 1.8800923630725743. Для обоих языков функция Fne закодирована для значений двойной точности и также возвращает значения двойной точности.

Код С++:

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

Не могли бы вы помочь мне найти, откуда эта разница?


person EL KESRI Amine    schedule 26.05.2015    source источник


Ответы (2)


Одним из источников различий является обработка по умолчанию C++ и Fortran литеральных констант, таких как 0.124. По умолчанию Fortran будет рассматривать это как число с плавающей запятой одинарной точности (почти на любом компьютере и комбинации компилятора, которую вы, вероятно, будете использовать), в то время как C++ будет рассматривать это как число f-p двойной точности.

В Fortran вы можете указать kind числа f-p (или любую другую встроенную числовую константу в этом отношении и при отсутствии каких-либо параметров компилятора для изменения наиболее вероятного поведения по умолчанию), добавив суффикс kind-selector следующим образом

0.124_8

Попробуйте это, посмотрите, какие результаты.

О, и пока я пишу, почему вы пишете на Фортране, как будто это был 1977 год? И всем другим экспертам по Фортрану, которые находятся поблизости, да, я знаю, что *8 и _8 не лучшая практика, но в данный момент у меня нет времени, чтобы распространяться обо всем этом.

person High Performance Mark    schedule 26.05.2015
comment
да, это работает, теперь у меня такая же точность, большое спасибо за вашу помощь - person EL KESRI Amine; 26.05.2015
comment
Что касается того, как я пишу на фортране, это не совсем мой код, моя работа на самом деле состоит в преобразовании длинной программы на фортране 77 в программу на С++. - person EL KESRI Amine; 26.05.2015
comment
@ELKESRIamine Если это ответ на ваш вопрос, рассмотрите возможность пометить его как правильный ответ. - person Avi Ginsburg; 26.05.2015

Как указал 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

это та же разница, которую вы заметили.

person Avi Ginsburg    schedule 26.05.2015