Non vi è alcun caso in cui una divisione per zero può avvenire qui.
La SMT Risolutore Z3 supporta IEEE preciso aritmetica in virgola mobile. Chiediamo a Z3 di trovare numeri a
e b
tali che 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)
Il risultato è UNSAT
. Non ci sono tali numeri.
La stringa SMTLIB precedente consente inoltre a Z3 di scegliere una modalità di arrotondamento arbitraria ( rm
). Ciò significa che il risultato vale per tutte le possibili modalità di arrotondamento (di cui ci sono cinque). Il risultato include anche la possibilità che una qualsiasi delle variabili in gioco possa essere NaN
o infinito.
a == b
è implementato come fp.eq
qualità in modo che +0f
e -0f
confrontare uguale. Anche il confronto con zero viene implementato fp.eq
. Poiché la domanda è volta ad evitare una divisione per zero, questo è il confronto appropriato.
Se il test di uguaglianza fosse stato implementato usando l'uguaglianza bit a bit +0f
e -0f
sarebbe stato un modo per fare a - b
zero. Una versione precedente errata di questa risposta contiene i dettagli della modalità su quel caso per i curiosi.
Z3 Online non supporta ancora la teoria FPA. Questo risultato è stato ottenuto utilizzando l'ultimo ramo instabile. Può essere riprodotto usando i collegamenti .NET come segue:
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);
Utilizzando Z3 per rispondere alle domande IEEE float è bello perché è difficile ignorare i casi (come ad esempio NaN
, -0f
, +-inf
) e si possono porre domande arbitrarie. Non è necessario interpretare e citare le specifiche. Puoi anche porre domande miste float e numeri interi come "questo int log2(float)
algoritmo particolare è corretto?".