Não há nenhum caso em que uma divisão por zero possa acontecer aqui.
O SMT Solver Z3 suporta aritmética precisa de ponto flutuante IEEE. Vamos pedir ao Z3 para encontrar números a
e b
tais 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)
O resultado é UNSAT
. Não existem tais números.
A sequência SMTLIB acima também permite que o Z3 escolha um modo de arredondamento arbitrário ( rm
). Isso significa que o resultado é válido para todos os modos de arredondamento possíveis (dos quais existem cinco). O resultado também inclui a possibilidade de qualquer uma das variáveis em jogo ser NaN
ou infinita.
a == b
é implementado como fp.eq
qualidade para que +0f
e -0f
comparar igual. A comparação com zero é implementada usando fp.eq
também. Como a pergunta visa evitar uma divisão por zero, esta é a comparação apropriada.
Se o teste de igualdade foi implementado usando a igualdade bit a bit, +0f
e-0f
tivesse sido uma maneira de fazera - b
zero. Uma versão anterior incorreta desta resposta contém detalhes do modo sobre esse caso para os curiosos.
O Z3 Online ainda não suporta a teoria da FPA. Este resultado foi obtido usando o último ramo instável. Ele pode ser reproduzido usando as ligações do .NET da seguinte maneira:
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);
Usando Z3 para responder a perguntas IEEE flutuador é bom porque é difícil ignorar casos (como NaN
, -0f
, +-inf
) e você pode fazer perguntas arbitrárias. Não há necessidade de interpretar e citar especificações. Você pode até fazer perguntas inteiras de float e float, como "este int log2(float)
algoritmo específico está correto?".