2015-05-26 2 views
0

Мне нужно преобразовать Fortran кода в один на C++ и у меня есть следующая проблема:неправильно точность для двойных значений

Я пытаюсь вычислить двойное значение имени R12 с обоих языков Fortran-77 и C++, но я полученные два значения очень близко друг к другу, но с двумя разными точками. вот мой код Fortran:

R12 = sqrt(95699.68D0+1123.6D0*flx) - 408.99D0 

с double flx = 192.9D0. Значение я получаю это R12 = 149.97522253177789

я сделать то же самое с C++:

R12 = sqrt(95699.68+1123.6*flx) - 408.99 ; 

значение я получаю здесь R12 = 149.97522253177794.

Может вы, ребята, пожалуйста, помогите мне найти, где эта разница с, потому что это очень важно для моей работы, чтобы иметь точную точность

+3

Определить "точную точность"? Используя значения с плавающей запятой, у вас никогда не будет «точной точности», и для иррациональных чисел вам понадобится бесконечная точность. 'double' имеет 15-17 чисел точности, и это то, что вы здесь. –

+0

Вы также можете прочитать об этом здесь: http://en.wikipedia.org/wiki/Machine_epsilon – CppChris

+0

Вы проверили, что (1) результат умножения идентичен на обоих языках? (2) результат сложения идентичен на обоих языках? (3) результат «sqrt» идентичен на обоих языках? Вам нужно разобраться в сути проблемы * перед тем, как спросить о SO. –

ответ

5

С двойной точностью, у вас есть 52 bits (roughly 15 decimals) из мантиссы точности. В вашем случае это:

Fortran:

0.14997522253177789e3 
       ^

C++

0.14997522253177794e3 
       ^

Вы можете видеть, что оба результата идентичны вплоть до 15-го разряда. Я предполагаю, что C++ и Fortran применяют другое преобразование (округление) к десятичной системе.

В Fortran 2003+ вы можете дать ROUND спецификатор к write:

program test 

    write(*,*)      'Default ', sqrt(95699.68D0+1123.6D0*192.9D0) - 408.99D0 
    write(*,*,round='UP')   'UP   ', sqrt(95699.68D0+1123.6D0*192.9D0) - 408.99D0 
    write(*,*,round='DOWN')  'DOWN  ', sqrt(95699.68D0+1123.6D0*192.9D0) - 408.99D0 
    write(*,*,round='ZERO')  'ZERO  ', sqrt(95699.68D0+1123.6D0*192.9D0) - 408.99D0 
    write(*,*,round='NEAREST')  'NEAREST ', sqrt(95699.68D0+1123.6D0*192.9D0) - 408.99D0 

end program 

результаты в

Default 149.97522253177794  
UP  149.97522253177795  
DOWN  149.97522253177794  
ZERO  149.97522253177794  
NEAREST 149.97522253177794 
+0

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

+1

Я предполагаю, что числа идентичны в * двоичном представлении *, но вы должен проверить это! BTW: Я получаю точно такой же результат в Fortran, когда вы попадаете на C++ ... –

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