Здесь не может быть деления на ноль.
SMT Solver Z3 поддерживает точную IEEE арифметику с плавающей точкой. Давайте попросим Z3 найти числа aи bтакие, что a != b && (a - b) == 0:
(set-info :status unknown)
(set-logic QF_FP)
(declare-fun b () (FloatingPoint 8 24))
(declare-fun a () (FloatingPoint 8 24))
(declare-fun rm () RoundingMode)
(assert
(and (not (fp.eq a b)) (fp.eq (fp.sub rm a b) +zero) true))
(check-sat)
Результат UNSAT . Таких номеров нет.
Вышеупомянутая строка SMTLIB также позволяет Z3 выбрать произвольный режим округления ( rm). Это означает, что результат верен для всех возможных режимов округления (их пять). Результат также включает возможность того, что любая из переменных в игре может иметь значение NaNили бесконечность.
a == bреализовано как fp.eqкачество, так что +0fи -0fсравнивать равно. Сравнение с нулем осуществляется с помощьюfp.eq . Поскольку вопрос направлен на то, чтобы избежать деления на ноль, это подходящее сравнение.
Если бы проверка на равенство была реализована с использованием побитового равенства, +0fи -0fэто был бы способ сделать a - bноль. Некорректная предыдущая версия этого ответа содержит подробные сведения о режиме для любопытных.
Z3 Online пока не поддерживает теорию FPA. Этот результат был получен с использованием последней нестабильной ветки. Его можно воспроизвести с помощью привязок .NET следующим образом:
var fpSort = context.MkFPSort32();
var aExpr = (FPExpr)context.MkConst("a", fpSort);
var bExpr = (FPExpr)context.MkConst("b", fpSort);
var rmExpr = (FPRMExpr)context.MkConst("rm", context.MkFPRoundingModeSort());
var fpZero = context.MkFP(0f, fpSort);
var subExpr = context.MkFPSub(rmExpr, aExpr, bExpr);
var constraintExpr = context.MkAnd(
context.MkNot(context.MkFPEq(aExpr, bExpr)),
context.MkFPEq(subExpr, fpZero),
context.MkTrue()
);
var smtlibString = context.BenchmarkToSMTString(null, "QF_FP", null, null, new BoolExpr[0], constraintExpr);
var solver = context.MkSimpleSolver();
solver.Assert(constraintExpr);
var status = solver.Check();
Console.WriteLine(status);
Использование Z3 , чтобы ответить на вопросы IEEE с плавающей точкой приятно , потому что это трудно игнорировать случаи (например NaN, -0f, +-inf) , и вы можете задать произвольные вопросы. Нет необходимости интерпретировать и цитировать спецификации. Вы даже можете задавать смешанные вопросы с числами с плавающей запятой и целыми числами, такие как « int log2(float)правильный ли этот алгоритм?».