Я ищу способы заставить gcc соблюдать определенный порядок операций (это не обязательно должен быть порядок, который минимизирует ошибку с плавающей запятой, просто порядок, в котором я бы хотел) относительно арифметики двойной точности конкретного разделакода, допуская полный -O3 -funsafe-math-optimizations
в другом месте.Я видел несколько постов по этому вопросу:
Являются ли операции с плавающей запятой в C ассоциативными?
https://devblogs.microsoft.com/cppblog/do-you-prefer-fast-or-precise/
C /Математический порядок операций C ++
Приведенные выше ссылки обсуждают глобальные параметры, но я хотел бы понять, существуют ли локальные директивы компилятора.Например, при аппаратном синтезе можно заставить компилятор дословно синтезировать логическое выражение без каких-либо сокращений.
Например, рассмотрим
#include <iostream>
#include <string>
#include <iomanip>
using std::cout;
int main()
{
double a = 1.0 + 1.3e-16;
double b = 1.0;
double c = 100.0;
double d = (a - b) / c;
double e = a / c - b / c;
cout << std::scientific;
cout << "Calculation d = " << d << "\n";
cout << "Calculation e = " << e << "\n";
double f = 1.0;
double g = 2e-15;
double h = 1.0;
double i = 1e-15;
double j = (f + g) - (h + i);
double k = (f - h) + (g - i);
double m = f + g - h - i;
double n = f - h + g - i;
cout << "Calculation j = " << j << "\n";
cout << "Calculation k = " << k << "\n";
cout << "Calculation m = " << m << "\n";
cout << "Calculation n = " << n << "\n";
}
Использование http://cpp.sh, Я получаю
Calculation d = 2.220446e-18
Calculation e = 1.734723e-18
Calculation j = 8.881784e-16
Calculation k = 1.000000e-15
Calculation m = 9.984014e-16
Calculation n = 1.000000e-15
Это не зависело от уровня оптимизации, который я использовал, поэтому кажется, что компилятор будет вычислять вещи в порядке, который я ожидаю, основываясь на выражении, плюс даже поддерживает порядок слева направо для+/- Но абсолютно ли это гарантировано, когда оптимизация включена?
Я могу придумать сценарий, например, где один из операндов уже находится в каком-то полезном регистре, в результате чего он сохранит некоторую часть памяти, перемещенную ввычислить вещи в другом порядке, чем я написал, но сохранил бы символьную корректность.
В принципе, я не могу начать пробовать разные способы взлома, чтобы решить проблему, например, я прочитал, что объявление субпродуктов в качестве изменчивых переменных будетпомощь, так как мой пример не показывает проблему.Поэтому я хотел бы знать, действительно ли это не проблема, или, если нет, какие уловки существуют.