You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Z3 C++ API浮点运算(FPA)使用咨询:代码报错与示例需求

Z3 C++ API 使用FPA求解非线性问题的解决方案

你的代码存在的问题

你遇到的断言错误,核心原因是错误使用了Z3_mk_fpa_fp函数:这个函数的作用是基于给定的符号位、指数位、尾数位的具体BV值,构造一个确定的浮点数实例,而不是用来声明浮点类型的变量。你的代码直接用未约束的BV变量调用它,完全不符合函数的使用场景,自然会触发断言失败。

另外你漏掉了关键步骤:没有先定义浮点类型(sort),就试图创建浮点变量,这也是导致错误的原因之一。

Z3 C++ API 使用FPA的完整示例

下面是适配你需求的完整代码,用32位单精度浮点数(对应C++的float)替代实数,实现x*y > 10的求解逻辑,还支持生成多个解:

#include <z3++.h>
#include <iostream>

using namespace z3;

int main() {
    // 初始化配置与上下文
    config cfg;
    cfg.set("auto_config", true);
    context con(cfg);

    // 创建32位单精度浮点类型:1位符号位 + 8位指数位 + 23位尾数位
    sort fp_sort = to_sort(con, Z3_mk_fpa_sort(con, 1, 8, 23));

    // 声明浮点类型的变量x和y
    expr x = con.constant("x", fp_sort);
    expr y = con.constant("y", fp_sort);

    solver sol(con);
    // 将整数10转换为对应浮点类型的常量,确保约束类型一致
    expr ten = to_expr(con, Z3_mk_fpa_from_real(con, con.real_val(10), 1, 8, 23));
    // 添加约束:x*y > 10
    sol.add(mul(x, y) > ten);

    // 求解并获取第一个解
    check_result res = sol.check();
    if (res == sat) {
        model m = sol.get_model();
        std::cout << "第一个解:" << std::endl;
        std::cout << "x = " << m.eval(x) << std::endl;
        std::cout << "y = " << m.eval(y) << std::endl;

        // 添加约束排除当前解,生成第二个解
        sol.add(x != m.eval(x) || y != m.eval(y));
        res = sol.check();
        if (res == sat) {
            model m2 = sol.get_model();
            std::cout << "\n第二个解:" << std::endl;
            std::cout << "x = " << m2.eval(x) << std::endl;
            std::cout << "y = " << m2.eval(y) << std::endl;
        } else {
            std::cout << "\n没有更多解了" << std::endl;
        }
    } else {
        std::cout << "无解" << std::endl;
    }

    return 0;
}

代码关键说明

  1. 浮点类型定义:用Z3_mk_fpa_sort创建自定义浮点类型,参数依次是符号位长度、指数位长度、尾数位长度。如果你的精度需求更低(仅1-2位小数),可以用更精简的格式,比如1位符号+5位指数+10位尾数(总16位),既能满足精度要求,又能进一步缩小搜索空间提升速度。
  2. 变量声明:通过con.constant基于浮点类型声明变量,这才是创建浮点变量的正确方式。
  3. 常量类型匹配:必须把实数/整数常量转换为对应浮点类型,用Z3_mk_fpa_from_real完成,避免类型不匹配的错误。
  4. 生成多解:每次求解后,添加排除当前解的约束(x != 当前x值 || y != 当前y值),再次调用solver.check()即可得到新解。

额外优化建议

如果不需要处理NaN、无穷大等特殊浮点值,可以添加约束排除这些情况,让求解更贴合业务场景:

// 确保x和y是正常的浮点数(非NaN、非无穷大)
sol.add(is_normal(x));
sol.add(is_normal(y));

内容的提问来源于stack exchange,提问作者Rehab11

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 07:47:34