Стандарт C ++ позволяет реализации оценивать выражения с плавающей точкой с большей точностью, чем это требуется для номинального формата. Например, выражения float
могут оцениваться, как если бы они были double
или более, а выражения double
могут оцениваться, как если бы они были long double
. Эта дополнительная точность может вызвать различия в оценке, особенно когда используются прерывистые функции (например, преобразование в int
).
Например, если y = 89
, y / 10.0 - y / 10
будет 0,9 в действительном числе арифметическое c, но 0,9000000000000003552713678800500929355621337890625 в double
(бинарный код IEEE-754) арифметическое c и 0,899999999999999999653055304804638581117615103721618 * * * 10 * с префиксом 10 *, 10 *, преобразование в 10-битное форматирование с ускорением в 10-битном формате, с разрешением 10-го и 10-го форматов, в том числе в 10-битном формате с разрешением 10-го и 10-го форматов, в том числе в форматах: 1012 * производит 9 или 8 соответственно.
При отключенной оптимизации компилятор может вычислять выражение с y
во время выполнения и выражение с 89
во время компиляции, и он может использовать разные точность для них. При оптимизации компилятор, вероятно, распознает y
, фактически являющуюся константой 89
в первом выражении, и оценивает оба выражения во время компиляции, используя один и тот же метод для обоих.
Стандарт C ++ требует, чтобы приведение и Операции присваивания преобразуются в номинальный тип, поэтому одним из тестов, чтобы увидеть, происходит ли это, является вставка приведений:
int foo = (double) ((double) (y / 10.0) - y / 10) * 10;
int bar = (double) ((double) (89 / 10.0) - 89 / 10) * 10;
Если это приводит к идентичности foo
и bar
, что поддерживает гипотезу. У вашего компилятора могут быть переключатели для управления оценкой выражений с плавающей точкой.
Еще один тест - включить <cfloat>
и вывести значение FLT_EVAL_METHOD
. Если оно равно 0, реализация утверждает, что оценивает операции с плавающей запятой в их номинальном типе, и такое поведение не должно происходить. Если оно равно 1 или 2, реализация утверждает, что использует double
или long double
для оценки double
выражений соответственно, и такое поведение снова не должно происходить, поскольку оба выражения будут оцениваться одинаково. Если это -1, реализация не делает эти утверждения, и поведение может произойти.
Чтобы получить последний di git неотрицательного целого числа, используйте y % 10
.