Если x является double, гарантируется (x - x) +0.0, или иногда оно может быть -0.0 (в зависимости от знака x)?
Является ли (x - x) всегда положительным ноль для удвоений или иногда отрицательным нолем?
Ответ 1
 x - x может быть +0.0 или NaN. Никаких других значений, которые он может принимать в арифметике IEEE 754 в раунде до ближайшего (и в Java, режим округления всегда от ближайшего к ближайшему). Вычитание двух идентичных конечных значений определяется как создание +0.0 в этом режиме округления. Марк Дикинсон, в комментариях ниже, ссылается на стандарт IEEE 754, говорящий в разделе 6.3:
Когда сумма двух операндов с противоположными знаками (или разностью двух операндов с одинаковыми знаками) равна нулю, знак этой суммы (или разности) должен быть +0 во всех атрибутах округления, кроме roundTowardNegative [...].
Эта страница показывает, что в частности 0.0 - 0.0 и -0.0 - (-0.0) являются +0.0.
Инфиниты и NaN оба производят NaN при вычитании из них.
Ответ 2
Решение SMT Z3 поддерживает арифметику IEEE с плавающей запятой. Попросите Z3 найти случай, когда x - x != 0. Он сразу находит NaN, а также +-infinity. Исключая их, не существует x, удовлетворяющего этому уравнению.
(set-logic QF_FPA)    
(declare-const x (_ FP 11 53))
(declare-const r (_ FP 11 53))
(assert (and 
    (not (= x (as NaN (_ FP 11 53))))
    (not (= x (as plusInfinity (_ FP 11 53))))
    (not (= x (as minusInfinity (_ FP 11 53))))
    (= r (- roundTowardZero x x))
    (not (= r ((_ asFloat 11 53) roundTowardZero 0.0 0)))
))
(check-sat)
(get-model)
Z3 реализует арифметику с плавающей запятой IEEE, преобразовывая все операции в логические схемы и используя стандартный SAT-решатель для поиска модели. Запрет на любые ошибки в этом переводе или SAT-решатель является абсолютно точным.
Доказательство для...
- ... 
roundTowardZero: http://rise4fun.com/Z3/7H4 - ... 
roundNearestTiesToEven: http://rise4fun.com/Z3/Opl4W 
Обратите внимание на контрпример для режима округления roundTowardNegative: http://rise4fun.com/Z3/T845. Для некоторого x результат x - x отрицательный ноль. Такой случай вряд ли может быть обнаружен людьми. Тем не менее, с решателем SMT легко найти. Мы можем изменить = на ==, чтобы Z3 вместо семантики сравнения IEEE использовала вместо точного равенства. После этого изменения снова нет встречного примера, поскольку -0 == +0 в соответствии с IEEE.
Я попытался сделать режим округления переменной. Это будет работать теоретически, но у Z3 есть ошибка. Сейчас нам нужно вручную указать режим округлого кодирования. Если бы мы могли сделать это переменной, мы могли бы попросить Z3 доказать это утверждение для всех режимов округления в одном запросе.