Как использовать расширенную точность с плавающей точкой в ​​системах MacOs или Windows - PullRequest
1 голос
/ 07 октября 2011

Этот маленький кусочек кода сводит меня с ума:

#include <stdio.h>

    int main() 
{
double x;
const double d=0.1;
x=d ;
for (int i=0; i<30; i++) 
    {
    printf("Cycle %d  Value :%.20e \n",i,x);
    x=x*(double)11.-(double)10*d; //11*0.1 = 1.1 - 10*0.1 = 1 => 0.1

    }       
return 0;
}

На самом деле я пытался продемонстрировать патологический случай из-за внутреннего представления плавающих чисел в стандарте IEEE 754.На компьютере MacOs или Windows последняя строка вывода будет иметь следующий вид:

Цикл 29 Значение: 1.28084153156127500000e + 13

Но в Linux (Scientific Linux 5.4) код будет работать без проблем.Чтение Я обнаружил, что:

В системах BSD, таких как FreeBSD, NetBSD и OpenBSD, аппаратный режим округления с двойной точностью является значением по умолчанию, обеспечивая наибольшую совместимость с собственными платформами двойной точности.В системах x86 GNU / Linux режим по умолчанию - расширенная точность (с целью обеспечения повышенной точности).

На той же странице GCC INTRO объяснялось, как включить двойную точностьокругление в системе Linux, но не как использовать расширенную точность в других системах.Это возможно на MacOs или Windows?и как?

1 Ответ

3 голосов
/ 07 октября 2011

Просто с использованием расширенной точности в OS X легко:

x=11.L*x - 10.L*d;

Суффикс L приводит к тому, что два литерала равны long double с вместо double с,что заставляет оценивать все выражение в 80-битном расширении согласно правилам вычисления выражений языка C.

Помимо этого, в вашем вопросе, похоже, есть некоторая путаница;вы говорите "... в Linux код будет работать без проблем".Пара моментов:

  • И результат OS X, и результат Linux соответствуют IEEE-754 и стандарту C.Не существует «проблемы» ни с одним из них.
  • Результат OS X воспроизводится на оборудовании, которое не поддерживает (нестандартный) 80-битный тип с плавающей запятой.Результат Linux не таков.
  • Вычисления, которые зависят от промежуточных результатов, хранящихся в расширенном 80-битном формате, являются хрупкими;изменение параметров компилятора, параметров оптимизации или даже потока программы может привести к изменению результата.Результат OS X будет стабильным при таких изменениях.

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

Для каждого случая, когда автоматическое использование расширенной точности сохраняло наивныйпользователь с плавающей точкой, я могу показать вам случай, когда непредсказуемость этого режима оценки приводит к тонкой и трудно диагностируемой ошибке.Их обычно называют ошибками «повышенной точности»;Одним из самых известных недавних примеров была ошибка, которая позволяла пользователям помещать 2.2250738585072011e-308 в веб-форму и сбой сервера .Конечная причина заключается именно в том, что компилятор идет за спиной программиста и поддерживает большую точность, чем было указано.Эта ошибка не была затронута OS X, поскольку выражения с двойной точностью вычисляются с двойной точностью, а не с расширенными.

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

...