Nie ma przypadku, w którym może wystąpić tutaj dzielenie przez zero.
SMT Solver Z3 umożliwia precyzyjną IEEE zmiennoprzecinkowych arytmetycznych. Poprośmy Z3 o znalezienie liczb a
i b
takie, że 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)
Wynik jest UNSAT
. Nie ma takich numerów.
Powyższy ciąg SMTLIB pozwala również Z3 na wybranie dowolnego trybu zaokrąglania ( rm
). Oznacza to, że wynik zachowuje się dla wszystkich możliwych trybów zaokrąglania (z których jest pięć). Wynik obejmuje również możliwość, że dowolna ze zmiennych w grze może być NaN
nieskończona.
a == b
jest wdrażany jako fp.eq
jakość, aby +0f
i -0f
porównać równe. Porównanie z zerem jest również realizowane za pomocą fp.eq
. Ponieważ pytanie ma na celu uniknięcie dzielenia przez zero, jest to właściwe porównanie.
Gdyby test równości został zaimplementowany przy użyciu równości bitowej +0f
i -0f
byłby sposobem na zrobienie a - b
zera. Niepoprawna poprzednia wersja tej odpowiedzi zawiera szczegółowe informacje dotyczące trybu dla ciekawskich.
Z3 Online nie wspiera jeszcze teorii FPA. Wynik ten uzyskano przy użyciu najnowszej niestabilnej gałęzi. Można go odtworzyć za pomocą powiązań .NET w następujący sposób:
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);
Korzystanie Z3 odpowiedzieć na pytania IEEE pływak jest dobre, bo trudno jest przeoczyć przypadków (takich jak NaN
, -0f
, +-inf
) i można zadać dowolne pytania. Nie ma potrzeby interpretowania i cytowania specyfikacji. Możesz nawet zadawać mieszane pytania typu float i integer, takie jak „czy ten konkretny int log2(float)
algorytm jest poprawny?”.