2015-09-29 2 views
0

У меня есть код следующим образом:выражение Intel Fortran возвращает неправильный результат

program th 
    implicit none 

    integer N1 
    integer maxi,ei,Nc,ns,na 
    real CH1,CH2 



    OPEN(unit=1,file='input_file',status="old") 
    read(1,*) ns      !!! 
    read(1,*) ei       !!!!!!!!!!!!!!! 
    read(1,*) maxi!!!!!!!!!!!!!!!!!!!  
    read(1,*) N1!!!!!!!!!!!!!!!! 
    close(unit=1) 


    CH1 = 0.07 
    CH2 = -0.35 


    Na = INT(abs(2.*((N1/2)*CH1 + (N1/2)*CH2))) 
    write(*,*) Na,abs(2.*((real(N1)/2.)*CH1 + (real(N1)/2.)*CH2));stop 
end program th 

и входной файл является

1      !!!!!!!!!!! 
1       !!!!!!!!!! 
1     !!! 
1600 

Тогда я скомпилировать его с

ifort -O3 -autodouble t1.f90 -o out 

, но когда я выполните его, я получаю 447 для na, что является неправильным. Правильный ответ - 448.

+0

Да, это должно быть 448. Что произойдет, если вы удалите INT()? В любом случае это Integer. Как насчет того, если вы скомпилируете его без -autodouble? – Dijkgraaf

+0

Проблема в том, что мне нужно autodouble в остальной части кода –

+0

Да, я не говорю, что нужно удалить его навсегда, но просто попробуйте его для этого кода. Это может быть какая-то ошибка двоичной ошибки. Попытка этих вещей может помочь сузить его. – Dijkgraaf

ответ

2

Эта проблема может быть понята путем исследования номеров до их полной точности.

Номер 0.07: 7.0000000298023224E-02 в одиночной точности и 7.0000000000000007E-02 в двойной точности. Номер 800 может быть представлен точно в обеих моделях.

Однако продукт этих чисел составляет приблизительно 56.000000238418579 и 56.000000000000006, соответственно. Из-за доступной точности первый округляется до 56 (в одной точности), а второй - в сторону 56.000000000000007 (с двойной точностью).

В результате расчет в единой точности «получает» некоторую точность округлением в «правильном» направлении.

Относительно различного поведения ifort 16, упомянутого в статье @casey, я полагаю, что существуют некоторые различия в перестановке уравнения или, возможно, использование избыточной точности для промежуточных результатов. Хотя, это только догадка.

+0

Когда я удаляю входной файл _file и помещаю переменную в код, я получаю правильное значение 448. Не могли бы вы рассказать, почему это происходит? –

+1

Не знаю. Выход ассемблера ('-S') должен помочь нам здесь, но у меня нет подсказки. Я предполагаю, что во время компиляции есть некоторые оптимизации, которые предварительно вычисляют некоторые результаты с различной точностью. Фактически, теперь существует разница между (N1/2) * CH1 + (N1/2) * CH2' и '(N1/2) * (CH1 + CH2)'. – Stefan

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