Когда я выполняю простое приложение x64 со следующим кодом, я получаю разные результаты на ПК с Windows с процессором i7-3770 и i7-4790.
#include <cmath>
#include <iostream>
#include <limits>
void main()
{
double val = exp(-10.240990982718174);
std::cout.precision(std::numeric_limits<double>::max_digits10);
std::cout << val;
}
Результат на i7-3770:
3.5677476354876406e-05
Результат на i7-4790:
3.5677476354876413e-05
Когда я изменяю код для вызова
unsigned int control_word;
_controlfp_s(&control_word, _RC_UP, MCW_RC);
до вызова функции exp оба процессора выдают одинаковые результаты.
Мои вопросы:
Предполагая, что double кодируется с использованием IEEE-754, и используя это десятичный в двоичный преобразователь, ты это видишь:
3.5677476354876406e-05 представлен в гекса как 0x3F02B48CC0D0ABA8
3.5677476354876413e-05 представлен в гекса как 0x3F02B48CC0D0ABA9
которые отличаются только последним битом, вероятно, из-за ошибки округления.
Я провел дальнейшие расследования и выяснил следующие факты:
Я также разместил этот вопрос в сообществе Visual Studio. Я получил информацию, что Haswell и более новые процессоры используют FMA3. Вы можете отключить эту функцию с _set_FMA3_enable (0) в начале программы. Когда я делаю это, результаты совпадают.