为什么 x = x * y / z 给出的结果与整数的 x *= y / z 不同?

Why does x = x * y / z give a different result from x *= y / z for integers?

提问人:Aditeya 提问时间:8/9/2022 最后编辑:Peter CordesAditeya 更新时间:6/9/2023 访问量:3737

问:

我有以下功能:

pub fn s_v1(n: &u64) -> u64 {
    let mut x: u64 = 1;

    for i in 1..=*n  {
        x = x * (*n + i) / i;
    }

    x
}

此代码给出了正确答案s_v1(&20) == 137846528820

但是,如果我将 for 循环中的行更改为x *= (*n + i) / i;

答案变为s_v1(&20) == 16094453760

为什么结果不同?不和 ?x = x * yx *= y

Rust 运算符优先级整 数除法 关联性

评论

8赞 n. m. could be an AI 8/9/2022
x = x * y是相同的,但你的表达式没有这种形式。那里有一个分裂。 与 不同。操作顺序不同x *= yx = x * y / zx *= y / z
22赞 qrsngky 8/9/2022
如果是整数除法,则 和 之间有区别,因为余数是如何被丢弃的/a * (b /c)(a * b) / c
0赞 Peter Cordes 8/9/2022
@qrsngky:是的,所有涉及的 3 个变量都有类型,所以这是整数除法。(函数 arg 是没有明显原因或好处的引用,因此取消引用它以获得 u64。u64u64*n
2赞 Ben Voigt 8/10/2022
您可以安全地更改为x = x * (*n + i) / i;x *= (*n + i); x /= i;
1赞 Ben Voigt 8/10/2022
请注意,该函数似乎正在计算 ,可以从一组 2n 个元素中绘制 n 个元素(不替换)的无序组合的数量nCr(2*n,n)

答:

33赞 Chayim Friedman 8/9/2022 #1

因为 和 与左关联性具有相同的优先级,所以表达式不是*/

x * ((*n + i) / i)

(与 相同)但x *= (*n + i) / i

(x * (*n + i)) / i

评论

3赞 Pablo H 8/10/2022
这两件事在精确算术上是相同的,所以根本原因不是(只是)优先级本身,而是整数算术。
11赞 Martin Kealey 8/10/2022 #2

正如其他人所指出的,有两个促成因素:

  1. a*=b/c等价于 和 not to(这是隐含的)。a=a*(b/c)a=a*b/ca=(a*b)/c
  2. /表示根据操作数的类型进行划分。在这种情况下,操作数都是整数,因此表示丢弃任何余数的整数除法,因此与 (除非是 的精确倍数)不同/(a*b)/ca*(b/c)bc

如果要替换循环中的行,则需要拆分两个操作:

    for i in 1..=*n  {
        x *= *n + i;
        x /= i;
    }

该算法的一个缺点是,当答案应该在 MAXINT/2n 和 MAXINT 之间时,它不会产生正确的结果。为此,您实际上需要利用您尝试执行的操作:

    for i in 1..=*n  {
        if (x % i == 0) {
            x /= i;
            x *= *n + i;
        } else if (*n % i == 0) {
            x *= *n / i + 1;
        } else {
            x *= *n + i;
            x /= i;
        }
    }