Il n'y a aucun cas où une division par zéro peut se produire ici.
Le SMT Solver Z3 prend en charge l'arithmétique précise à virgule flottante IEEE. Demandons à Z3 de trouver des nombres a
et b
tels que 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)
Le résultat est UNSAT
. Il n'y a pas de tels chiffres.
La chaîne SMTLIB ci-dessus permet également à Z3 de choisir un mode d'arrondi arbitraire ( rm
). Cela signifie que le résultat est valable pour tous les modes d'arrondi possibles (dont il y en a cinq). Le résultat inclut également la possibilité que l'une des variables en jeu soit NaN
ou l'infini.
a == b
est mis en œuvre en tant que fp.eq
qualité afin que +0f
et -0f
comparer égal. La comparaison avec zéro est également implémentée en utilisant fp.eq
. Puisque la question vise à éviter une division par zéro, c'est la comparaison appropriée.
Si le test d'égalité avait été implémenté en utilisant l'égalité au niveau du bit, +0f
et -0f
aurait été un moyen de fairea - b
zéro. Une version précédente incorrecte de cette réponse contient des détails de mode sur cette affaire pour les curieux.
Z3 Online ne prend pas encore en charge la théorie FPA. Ce résultat a été obtenu en utilisant la dernière branche instable. Il peut être reproduit à l'aide des liaisons .NET comme suit:
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);
En utilisant Z3 pour répondre aux questions float IEEE est agréable car il est difficile de négliger les cas ( par exemple NaN
, -0f
, +-inf
) et vous pouvez poser des questions arbitraires. Pas besoin d'interpréter et de citer des spécifications. Vous pouvez même poser des questions mixtes flottantes et entières telles que "cet int log2(float)
algorithme particulier est-il correct?".