Реальный ответ здесь - другой вопрос: почему вы думаете, что вам это нужно? Может быть лучший способ выполнить то, что вы пытаетесь сделать, который не зависит от сложных деталей платформы с плавающей точкой. Сказав это ...
К сожалению, вы не можете изменить код Linux, так как на самом деле результаты Linux являются здесь недостаточными. Результаты SUN настолько хороши, насколько это возможно: они правильно округлены; каждое умножение дает уникальный (в данном случае) C double, наиболее близкий к результату. Напротив, первое умножение Linux не дает правильно округленный результат.
Ваши результаты по Linux получены из 32-битной системы на оборудовании x86, верно? Результаты, которые вы показываете, соответствуют и, вероятно, вызваны явлением «двойного округления»: результат первого умножения сначала округляется до 64-битной точности (точности, используемой внутренним процессором Intel x87 FPU), а затем повторно основанный на обычной 53-битной точности двойного. Большую часть времени (примерно в 1999 году из 2000 или около того в среднем) этот двойной раунд имеет тот же эффект, что и одиночный раунд до 53-битной точности, но иногда он может давать другой результат, и это то, что вы ' видите здесь.
Как вы говорите, есть способы исправить результаты Linux так, чтобы они совпадали с результатами Solaris: один из них заключается в использовании соответствующих флагов компилятора для принудительного использования инструкций SSE2 для операций с плавающей запятой, если это возможно. В последнем выпуске gcc версии 4.5 также исправлена разница с помощью нового флага -fexcess-precision
, хотя это исправление может повлиять на производительность, если не использовать SSE2.
[Редактировать: после нескольких перечитываний руководств по gcc, ветки списка рассылки gcc-patches по адресу http://gcc.gnu.org/ml/gcc-patches/2008-11/msg00105.html, и связанного с ним отчета об ошибке gcc , мне все еще не ясно, будет ли использоваться -fexcess-precision=standard
фактически исключает двойное округление в системах x87; Я думаю, что ответ зависит от значения FLT_EVAL_METHOD. У меня нет 32-битной машины Linux / x86, чтобы проверить это.]
Но я не знаю, как бы вы исправили результаты Solaris, чтобы они соответствовали результатам Linux, и я не уверен, почему вы захотите: вы будете делать результаты Solaris менее точными, а не делать Результаты Linux более точны.
[Редактировать: у Кафа есть хорошее предложение здесь. На Solaris попробуйте сознательно использовать long double для промежуточных результатов, а затем принудительно вернуться к удвоению. Если все сделано правильно, это должно воспроизвести эффект двойного округления, который вы видите в Linux.]
См. Отличную статью Дэвида Моннио Подводные камни проверки вычислений с плавающей точкой для хорошего объяснения двойного округления. Это важно прочитать после статьи Гольдберга, упомянутой в предыдущем ответе.