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

jqwik链式Double生成器scale异常 咨询scale参数含义及设置方法

报错场景

使用jqwik链式double生成器时抛出如下异常:

java.util.concurrent.ExecutionException: net.jqwik.api.JqwikException: Decimal value -1.6099999999999999 cannot be represented with scale 4.

使用的生成器代码:

@Provide("close doubles")
Arbitrary<Tuple.Tuple2<Double,Double>> closeDoubles(@ForAll() Double aDouble) {
    return Arbitraries.doubles()
            .between(aDouble-2.5, aDouble+2.5)
            .withSpecialValue(aDouble)
            .ofScale(4)
            .map(num ->Tuple.of(aDouble,num));
}

目标需求为生成两个差值不超过2.5的相近double值。

ofScale参数含义
  • 该参数用于约束生成的浮点数,必须能够无歧义表示为小数点后最多N位的十进制数,设置为4时,所有生成值转换为十进制后小数位不会超过4位,再转换为double类型返回。
  • 报错的核心原因:外层通过@ForAll注入的aDouble是无精度约束的随机double,做aDouble-2.5这类算术运算时会出现原生浮点精度损失,生成类似-1.6099999999999999这类无法被精确舍入到4位小数的边界值,和ofScale(4)的约束直接冲突,触发异常。
正确配置方案

方案1:全链路统一精度约束(需要固定小数位时使用)

不要通过方法参数注入无约束的基准double,而是在生成器内部先定义和后续规则一致的基准值生成逻辑,通过flatMap链式生成,保证所有参与计算的数值都符合精度要求:

@Provide("close doubles")
Arbitrary<Tuple.Tuple2<Double,Double>> closeDoubles() {
    // 基准值同样约束为4位小数,避免计算边界时出现精度溢出
    Arbitrary<Double> baseArb = Arbitraries.doubles().ofScale(4);
    return baseArb.flatMap(baseVal -> 
        Arbitraries.doubles()
                .between(baseVal - 2.5, baseVal + 2.5)
                .ofScale(4)
                .withSpecialValue(baseVal)
                .map(closeVal -> Tuple.of(baseVal, closeVal))
    );
}

方案2:移除不必要的精度约束(无小数位要求时使用)

如果业务场景不需要强制固定小数位数,直接删除ofScale(4)调用即可,jqwik默认的double生成器会自动处理浮点边界问题,不会触发这类精度异常,同时完全满足“两值差值不超过2.5”的需求:

@Provide("close doubles")
Arbitrary<Tuple.Tuple2<Double,Double>> closeDoubles(@ForAll Double aDouble) {
    return Arbitraries.doubles()
            .between(aDouble - 2.5, aDouble + 2.5)
            .withSpecialValue(aDouble)
            .map(num -> Tuple.of(aDouble, num));
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 03:06:21