2010-05-03 2 views
6

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

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. То есть вычисленные значения равны только до шестого десятичного знака. Хотя я и не особенно сторонник Фортрана, я склонен рассматривать его результаты как «правильные», учитывая его законную репутацию числа cruncher. Однако я заинтригован причиной этой разницы между вычисленными значениями. Кто-нибудь знает, в чем причина этого несоответствия?

+1

http://docs.sun.com/source/806-3568/ncg_goldberg.html – 2010-05-03 10:40:03

+0

C++ результат является более правильным '0.8422012861950640318689334181' – jfs

+0

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

ответ

11

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

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

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

+1

Точно. Это распространенная ошибка - выражение с правой стороны не «знает», что переменная слева является двойной точностью. Способ FORTRAN 77 указать, что константа float является двойной точностью, заключается в добавлении суффикса «D0» - попробуйте добавить это к устаревшему файлу FORTRAN. –

+0

Спасибо вам обоим. Кроме того, только для справочных целей, и, как отметил J.F.Sebastian, -fdefault-real-8 можно использовать при компиляции с gfortran, чтобы использовать литералы с плавающей запятой двойной точности. – plok

+0

Я знаю, что это старая тема, но сегодня я узнал что-то очень ценное, которое фиксирует несоответствие, которое мы имеем в нашем коде. Спасибо @ M.S.B. для наконечника «D0». – jitihsk

Смежные вопросы