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

为何浮点数精确相等比较在黄金比例计算中始终有效?

为什么这个用浮点数精确相等比较的函数总能返回黄金比例?

我们常被教导不要对浮点数进行精确相等比较,但下面这个接收任意正数、返回黄金比例的函数,却用了double类型的精确相等判断,而且始终有效:

public static double f(double x) {
    double y;
    while ((y = 1 + 1 / x) != x)
        x = (x + y) / 2;
    return x;
}

@Test
void test() {
    assertEquals((1 + sqrt(5)) / 2, f(1.0));  // 测试通过!
}

原本以为只有部分输入能生效,但用JQwik做属性测试后,所有正输入都能通过:

@Property
void test2(@ForAll @Positive double x) {
    assertEquals((1 + sqrt(5)) / 2, f(x));  // 全部通过!
}

为什么这个循环里从未出现浮点数差值极小、无法触发精确相等的情况?


核心原因解析

  1. 黄金比例的浮点数特性
    真实的黄金比例φ满足数学等式:φ = 1 + 1/φ(等价于φ² = φ + 1)。而double是64位固定精度的浮点数,它对φ的近似值记为φ₀。当迭代收敛到φ₀时,在double的运算规则下,计算1 + 1/φ₀的结果会恰好等于φ₀——浮点数运算的舍入规则会让这个计算结果对齐到φ₀,而非产生一个接近但不等的值。

  2. 迭代过程的单调收敛性
    无论初始输入的正x是大于还是小于φ:

  • 如果x > φ,那么y = 1 + 1/x必然小于φ,两者的平均值(x+y)/2会比原x更靠近φ;
  • 如果x < φ,那么y = 1 + 1/x必然大于φ,平均值同样会向φ靠拢。
    这种单调收敛的特性,会让迭代快速逼近φ₀,不会出现来回震荡或无限逼近却达不到相等的情况。
  1. 有限步数内必然收敛
    double的精度约为15-17位有效数字,这个迭代过程只需要几步就能收敛到满足y == x的φ₀,不会陷入无限循环,也不会停留在差值极小但不等的状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 20:50:28