【问题标题】:Is there a way to assert that the first digit (most significant) of number is a particular digit?有没有办法断言数字的第一个数字(最高有效位)是一个特定的数字?
【发布时间】:2022-08-08 10:50:20
【问题描述】:

我想断言一个数字的最高位是一个特定的值,但我实际上并不知道数字的长度。如果它是最低有效数字,我知道我可以使用 python mod (%) 来检查它。但是由于位数未知,我不确定如何在 z3 中检查它。

例如,我可能知道最左边的数字是 9,例如 9x、或 9xx、或 9xxx 等。

非常感谢提前

    标签: z3 smt z3py


    【解决方案1】:

    执行此操作的通用方法是转换为字符串并检查第一个字符是否匹配:

    from z3 import *
    
    s = Solver()
    n = Int('n')
    
    s.add(SubString(IntToStr(n), 0, 1) == "9")
    
    r = s.check()
    
    if r == sat:
        m = s.model()
        print("n =", m[n])
    else:
        print("Solver said:", r)
    

    这打印:

    n = 9
    

    请注意,IntToStr 期望其参数为非负数,因此如果您需要支持负数,则必须编写额外的代码来适应它。有关详细信息,请参阅https://smtlib.cs.uiowa.edu/theories-UnicodeStrings.shtml

    在旁边虽然这将实现您想要的一般性,但它可能不是编码此约束的最有效方式。由于它通过字符串,生成的约束可能会导致性能问题。如果您的号码有上限,则明确编码可能会更有效。例如,如果您知道您的号码小于 1000,我会将其编码为(伪代码):

      n == 9 || n >= 90 && n <= 99 || n >= 900 && n <= 999
    

    等等,直到你覆盖了你需要的范围。这将导致更简单的约束并且总体上表现更好。请注意,即使您不知道确切的长度,但它有一个上限,这也会起作用。但是,当然,这完全取决于您要达到的目标以及您对数字本身的了解。

    【讨论】:

    • 谢谢,我对使用 z3 还是比较陌生,所以我不确定如何很好地使用字符串。我想我可以编写一个循环,将基数乘以 10 的幂,然后将 10 的幂减去 1 以得到下一个“下界”(9、99、999 等),直到值通过真正的上限阈值
    • 是的;您可以使用 Python 函数以编程方式生成此约束。试一试,如果证明很棘手,请随时发布一个新问题。
    猜你喜欢
    • 1970-01-01
    • 2020-06-09
    • 1970-01-01
    • 2012-01-10
    • 1970-01-01
    • 2020-02-09
    • 2021-10-04
    • 2023-01-31
    • 1970-01-01
    相关资源
    最近更新 更多