Расхождение между значениями, вычисленными с помощью Fortran и C ++ - PullRequest
6 голосов
/ 03 мая 2010

Я бы осмелился сказать, что числовые значения, вычисленные с помощью Fortran и C ++, были бы намного более похожими. Однако из того, что я испытываю, оказывается, что вычисленные числа начинают расходиться после слишком небольшого количества десятичных цифр. Я сталкивался с этой проблемой в процессе переноса устаревшего кода с первого языка на второй. Оригинальный код Fortran 77 ...

  INTEGER M, ROUND
  DOUBLE PRECISION NUMERATOR, DENOMINATOR

  M = 2
  ROUND = 1
  NUMERATOR=5./((M-1+(1.3**M))**1.8)
  DENOMINATOR = 0.7714+0.2286*(ROUND**3.82)
  WRITE (*, '(F20.15)') NUMERATOR/DENOMINATOR
  STOP

... выводит 0,842201471328735 , в то время как его эквивалент C ++ ...

int m = 2;
int round = 1;
long double numerator = 5.0 / pow((m-1)+pow(1.3, m), 1.8);
long double denominator = 0.7714 + 0.2286 * pow(round, 3.82);
std::cout << std::setiosflags(std::ios::fixed) << std::setprecision(15)
          << numerator/denominator << std::endl;
exit(1);

... возвращает 0,842201286195064 . То есть вычисленные значения равны только с точностью до шестого знака после запятой . Хотя я и не являюсь сторонником Фортрана, я склонен считать его результаты «правильными», учитывая его законную репутацию числового мошенника. Тем не менее, я заинтригован о причине этой разницы между вычисленными значениями. Кто-нибудь знает, в чем может быть причина этого несоответствия?

1 Ответ

11 голосов
/ 03 мая 2010

В Fortran по умолчанию литералы с плавающей точкой имеют одинарную точность, тогда как в C / C ++ они имеют двойную точность.

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

И то же самое для выражения, вычисляющего значение, назначенное переменной DENOMINATOR.

...