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

Java中ans *= (N-i+1)/i与ans=ans*(N-i+1)/i结果为何不同?

为什么ans *= (N-i+1)/i和ans = ans * (N-i+1)/i结果不一致?

在解决Unique Paths问题时,当输入m=51、n=9时,两种看似等价的迭代写法得到了完全不同的计算结果,核心原因是整数除法的运算顺序导致精度丢失的时机不同。

问题重现

写法1:使用ans *= (N-i+1)/i

public int uniquePaths(int m, int n) 
{
    double ans = 1;
    int N = m+n-2;
    int R = Math.min(n, m)-1;
    for(int i = 1; i <= R; i++)
    {
        ans *= (N-i+1)/i;
    }
    return (int)ans;
}

输出片段:

51/1
ans=58.0
52/2
ans=1624.0
53/3
ans=29232.0
...

写法2:使用ans = ans * (N-i+1)/i

public int uniquePaths(int m, int n) 
{
    double ans = 1;
    int N = m+n-2;
    int R = Math.min(n, m)-1;
    for(int i = 1; i <= R; i++)
    {
        System.out.println((N-R+i)+"/"+i);
        ans = ans * (N-i+1)/i;
        System.out.println("ans="+ans);
    }
    return (int)ans;
}

输出片段:

51/1
ans=58.0
52/2
ans=1653.0
53/3
ans=30856.0
...

核心原因分析

Java中,N、i都是int类型,整数除法会直接舍去小数部分,这是两种写法差异的关键:

  1. 写法1的运算顺序:
    ans *= (N-i+1)/i 等价于 ans = ans * ((N-i+1)/i)
    先执行(N-i+1)/i的整数除法,得到一个整数结果,再和ans(double类型)相乘。
    以i=2为例:(58-2+1)/2 = 57/2 = 28(整数除法舍去0.5),所以ans = 58 * 28 = 1624。

  2. 写法2的运算顺序:
    ans = ans * (N-i+1)/i 等价于 ans = (ans * (N-i+1)) / i
    先执行ans * (N-i+1):ans是double,N-i+1会自动转为double,相乘得到带小数的结果;再除以i(同样转为double),保留了小数部分。
    以i=2为例:58 * 57 = 3306(double类型),再除以2得到1653.0,没有丢失精度。

后续迭代中,写法1的整数除法误差会被不断放大,最终导致结果完全偏离正确值;而写法2通过先乘后除的浮点数运算,最大程度保留了精度,结果更接近正确的组合数计算值。

补充说明

Unique Paths的本质是计算组合数C(m+n-2, min(m,n)-1),正确的迭代计算应该优先保证运算过程中不丢失精度,写法2的逻辑更符合组合数的迭代计算规则(每次乘分子、除以分母,用浮点数或大整数类型避免精度损失)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.25 03:24:21