Тут немає жодного випадку, коли тут може відбутися поділ на нуль.
SMT Solver Z3 підтримує точну IEEE арифметику з плаваючою точкою. Попросимо Z3 знайти числа a
і b
таке 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)
Результат - UNSAT
. Таких номерів немає.
Вищевказана рядок SMTLIB також дозволяє Z3 вибрати режим довільного округлення ( rm
). Це означає, що результат справедливий для всіх можливих режимів округлення (їх п'ять). Результат також включає можливість, що будь-яка з змінних у грі може бути NaN
або нескінченною.
a == b
реалізуються як fp.eq
якість , так що +0f
і -0f
порівнювати одно. Порівняння з нулем реалізується і з використанням fp.eq
. Оскільки питання спрямоване на те, щоб уникнути поділу на нуль, це відповідне порівняння.
Якби тест на рівність здійснювався за допомогою побітової рівності, +0f
і -0f
це був би спосіб зробити a - b
нуль. Невірна попередня версія цієї відповіді містить детальну інформацію про цей випадок для допитливих.
Z3 Online ще не підтримує теорію FPA. Цей результат був отриманий за допомогою останньої нестабільної галузі. Його можна відтворити, використовуючи прив'язки .NET так:
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);
Використання Z3 , щоб відповісти на питання IEEE з плаваючою точкою перетину , тому що це важко ігнорувати випадки (наприклад NaN
, -0f
, +-inf
) , і ви можете задати довільні питання. Не потрібно тлумачити та цитувати технічні характеристики. Ви навіть можете задавати змішані питання з плаваючою чи цілою чисельністю, наприклад " int log2(float)
правильний цей алгоритм?"