Самая невинная перестройка выражений для
Самая невинная перестройка выражений для f 1 и f2, независимо от того, сделана она программистом или оптимизатором, может вызвать переход в условном операторе по другой ветке. Правильный способ проверки равенства с плавающей точкой состоит в том, чтобы ввести малую величину:
C |
if ((fabs(f2-f1))<Epsilon)...
и затем сравнить абсолютное значение разности с малой величиной. По той же самой причине нет существенного различия между < = и < при вычислениях с плавающей точкой.
Ошибки в вычислениях с плавающей точкой часто можно уменьшить изменением порядка действий. Поскольку сложение производится слева направо, четырехразрядное десятичное вычисление
1234.0 + 0.5678 + 0.5678 = 1234.0
лучше делать как:
0.5678 + 0.5678 + 1234.0 = 1235.0
чтобы не было исчезновения слагаемых.
В качестве другого примера рассмотрим арифметическое тождество:
(х+у)(х-у)=х2-у2
и используем его для улучшения точности вычисления:
X, Y: Float_4;
Z: Float_7;
Ada |
Z := Float_7(X*X - Y*Y); -- или так?
Если мы положим х = 1234.0 и у = 0.6, правильное значение этого выражения будет равно 1522755.64. Результаты, вычисленные с точностью до восьми цифр, таковы:
(1234.0 + 0.6) • (1234.0-0.6) =1235.0 • 1233.0=1522755.0
и
(1234.0 • 1234.0)-(0.6 • 0.6) = 1522756.0-0.36 =1522756.0
При вычислении (х + у) (х- у) небольшая ошибка, являющаяся результатом сложения и вычитания, значительно возрастает при умножении. При вычислении по формуле х2 - у2 уменьшается ошибка от исчезновения слагаемого и результат получается более точным.
9.4. Вещественные типы в языке Ada
Замечание: техническое определение вещественных типов было значительно упрощено при переходе от Ada 83 к Ada 95, поэтому, если вы предполагаете детально изучать эту тему, лучше опускать более старые определения.