Мое приложение генерирует разные значения с плавающей запятой, когда я компилирую его в режиме выпуска и в режиме отладки. Единственная причина, по которой я узнал, - это то, что я сохраняю журнал двоичной трассировки, а тот, который из сборочной версии, очень немного отличается от отладочной сборки, похоже, что два нижних бита 32-битных значений с плавающей запятой отличаются примерно на 1/2 случаев.
Считаете ли вы это "различие" ошибкой или такого рода различий можно было бы ожидать. Будет ли это ошибка компилятора или ошибка внутренней библиотеки.
Например:
LEFTPOS and SPACING are defined floating point values.
float def_x;
int xpos;
def_x = LEFTPOS + (xpos * (SPACING / 2));
Проблема в компиляторе X360.





Это не ошибка. Любая операция с плавающей запятой имеет некоторую неточность. В режиме Release оптимизация изменит порядок операций, и вы получите немного другой результат. Однако разница должна быть небольшой. Если он большой, у вас могут быть другие проблемы.
В режиме выпуска может быть установлена другая стратегия FP. Существуют различные режимы арифметики с плавающей запятой в зависимости от желаемого уровня оптимизации. Например, MSVC имеет строгий, быстрый и точный режимы.
Я помог коллеге найти переключатель компилятора, который отличался в выпуске от отладочной сборки, что вызывало его различия.
Взгляните на / fp (указать поведение с плавающей запятой).
Не ошибка. Такой разницы следовало ожидать.
Например, на некоторых платформах есть регистры с плавающей запятой, которые используют больше бит, чем хранится в памяти, поэтому сохранение значения в регистре может дать несколько иной результат по сравнению с сохранением в памяти и повторной загрузкой из памяти.
Это несоответствие вполне может быть вызвано оптимизацией компилятора, которая обычно выполняется в режиме выпуска, но не в режиме отладки. Например, компилятор может изменить порядок некоторых операций для ускорения выполнения, что, вероятно, может вызвать небольшую разницу в результатах с плавающей запятой.
Так что, скорее всего, это не ошибка. Если вас это действительно беспокоит, попробуйте включить оптимизацию в режиме отладки.
Я знаю, что на ПК регистры с плавающей запятой имеют ширину 80 бит. Таким образом, если вычисления выполняются полностью внутри FPU, вы получаете преимущество в 80 бит точности. С другой стороны, если промежуточный результат перемещается в нормальный регистр и обратно, он усекается до 32 бит, что дает разные результаты.
Теперь учтите, что сборка выпуска будет иметь оптимизацию, которая сохранит промежуточные результаты в регистрах FPU, тогда как сборка отладки, вероятно, будет наивно копировать промежуточные результаты назад и вперед между памятью и регистрами - и вот вам разница в поведении.
Не знаю, на X360 такое тоже происходит или нет.
Как и другие упомянутые, регистры с плавающей запятой имеют более высокую точность, чем числа с плавающей запятой, поэтому точность конечного результата зависит от распределения регистров.
Если вам нужны согласованные результаты, вы можете сделать переменные изменчивыми, что приведет к более медленным, менее точным, но согласованным результатам.
В дополнение к различным режимам с плавающей запятой, на которые указали другие, для выпуска могут быть включены SSE или аналогичные векторные оптимизации. Преобразование арифметики с плавающей запятой из стандартных регистров в векторные регистры может повлиять на младшие биты результатов, поскольку векторные регистры обычно будут более узкими (меньше битов), чем стандартные регистры с плавающей запятой.
Если вы установите переключатель компилятора, который позволяет компилятору переупорядочивать операции с плавающей запятой, - например, / fp: fast - тогда очевидно, что это не ошибка.
Если вы не установили такой переключатель, то это ошибка - стандарты C и C++ не позволяют компиляторам изменять порядок операций без вашего разрешения.