ไม่มีกรณีใดที่การหารด้วยศูนย์สามารถเกิดขึ้นได้ที่นี่
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)
อัลกอริทึมเฉพาะนี้ถูกต้องหรือไม่"