Проблемы межъязыкового языка Fortran / C: результаты отличаются 14-й цифрой - PullRequest
2 голосов
/ 24 января 2011

Я должен использовать C и Fortran вместе, чтобы сделать некоторые симуляции.В их курсе я использую одну и ту же память в обеих частях языка программирования, определяя указатель на C для доступа к памяти, выделенной Fortran.Тип данных проблемной переменной:

real(kind=8)

для Fortran и

double

для C. Результаты одних и тех же вычислений теперь различаются в зависимости от языка программирования, и мне нужноСравни их напрямую и получи ноль.Все расчеты сделаны только с указанными выше точностями.Разница всегда в 13-14-ой цифре.

Что было бы хорошим способом решить эту проблему?Какие-нибудь флаги компилятора?Просто отключить после нескольких цифр?

Большое спасибо!

Ответы [ 5 ]

2 голосов
/ 24 января 2011

Плавающая точка не совсем точна. Когда-либо. Даже cos(x) == cos(y) может быть ложным, если x == y.

Поэтому, когда вы проводите сравнение, примите это во внимание и позвольте значениям отличаться на небольшое значение эпсилона.

2 голосов
/ 25 января 2011

Одна вещь, которую вы можете проверить, это убедиться, что управляющее слово FPU одинаково в обоих случаях.Если он установлен на 53-битную точность в одном случае и 64-битный в другом, он, скорее всего, даст другие результаты.Вы можете использовать инструкции fstcw и fldcw, чтобы прочитать и загрузить значение контрольного слова.Тем не менее, как уже упоминали другие, вы не должны зависеть от точности идентичности, даже если вы можете заставить ее работать в одной ситуации.

2 голосов
/ 24 января 2011

Это проблема с неточностью с числами с плавающей запятой - они будут неточными и в определенном месте.Вы обычно сравниваете их либо округляя их до цифры, которая, как вы знаете, будет находиться в точной области, либо предоставляя эпсилон подходящего значения (достаточно маленький, чтобы не влиять на дальнейшие вычисления, и достаточно большой, чтобы позаботиться о неточности при сравнении).

1 голос
/ 26 января 2011

Поскольку вы компилируете для архитектуры x86, вполне вероятно, что один из компиляторов поддерживает промежуточные значения в регистрах с плавающей запятой, которые составляют 80 бит, в отличие от 64 бит C double.

Для GCC вы можете указать опцию -ffloat-store, чтобы запретить эту оптимизацию.Вам может также нужно изменить код, чтобы явно сохранять некоторые промежуточные результаты в double переменных.Некоторые эксперименты, вероятно, в порядке.

1 голос
/ 25 января 2011

Совершенной переносимости очень трудно достичь в операциях с плавающей запятой.Изменение порядка машинных инструкций может привести к изменению округления.Один компилятор может хранить значения в регистрах, а другой копировать их в память, что может изменить точность.В настоящее время языки Fortran и C допускают определенную широту.Модуль IEEE Fortran 2008, когда он будет реализован, позволит требовать более конкретных и, следовательно, более переносимых вычислений с плавающей запятой.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...