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

Adi*_*eya 12 integer-division operator-precedence associativity rust

我有以下功能:

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

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

    x
}
Run Code Online (Sandbox Code Playgroud)

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

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

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

为什么结果不同?不是x = x * y一样吗x *= y

Cha*_*man 33

因为*/与左结合性具有相同的优先级,所以该表达式不是

x * ((*n + i) / i)
Run Code Online (Sandbox Code Playgroud)

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

(x * (*n + i)) / i
Run Code Online (Sandbox Code Playgroud)

  • 这两件事在精确算术中是相同的,因此根本原因不仅仅是优先级本身,而是整数算术。 (3认同)

Mar*_*ley 11

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

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

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

    for i in 1..=*n  {
        x *= *n + i;
        x /= i;
    }
Run Code Online (Sandbox Code Playgroud)

该算法的一个缺点是,当答案应在 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;
        }
    }
Run Code Online (Sandbox Code Playgroud)