There is no case where a division by zero can happen here.
The SMT Solver Z3 supports precise IEEE floating point arithmetic. Let's ask Z3 to find numbers a
and b
such that 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)
The result is UNSAT
. There are no such numbers.
The above SMTLIB string also allows Z3 to pick an arbitrary rounding mode (rm
). This means that the result holds for all possible rounding modes (of which there are five). The result also includes the possibility that any of the variables in play might be NaN
or infinity.
a == b
is implemented as fp.eq
quality so that +0f
and -0f
compare equal. The comparison with zero is implemented using fp.eq
as well. Since the question is aimed at avoiding a division by zero this is the appropriate comparison.
If the equality test was implemented using bitwise equality, +0f
and -0f
would have been a way to make a - b
zero. An incorrect previous version of this answer contains mode details about that case for the curious.
Z3 Online does not yet support the FPA theory. This result was obtained using the latest unstable branch. It can be reproduced using the .NET bindings as follows:
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);
Using Z3 to answer IEEE float questions is nice because it is hard to overlook cases (such as NaN
, -0f
, +-inf
) and you can ask arbitrary questions. No need to interpret and cite specifications. You can even ask mixed float and integer questions such as "is this particular int log2(float)
algorithm correct?".
java.lang.Double.MIN_VALUE
to compare how small the difference is and force the result? Or evenjava.lang.Double.NEGATIVE_INFINITY
? – Kenzix
bits for the mantissa (precision), you're guaranteed at leastfloor(log10(2^x))
decimal digits of precision. – Centroclinal