这里不可能发生除以零的情况。
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) 算法是否正确?”。