在任何情况下都不会发生被零除的情况。
该SMT求解 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
or无限的可能性。
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)
算法正确吗?”。