As others have indicated, there are two contributing factors:
a*=b/c
is equivalent to a=a*(b/c)
and not to a=a*b/c
(which is implicitly a=(a*b)/c
).
/
denotes division according to the types of the operands. In this case the operands are both integers, and therefore /
denotes integer division discarding any remainder, and therefore (a*b)/c
is not the same as a*(b/c)
(unless b
is an exact multiple of c
).
If you want to replace the line in the loop, you'd need to split the two operations:
for i in 1..=*n {
x *= *n + i;
x /= i;
}
One disadvantage of this algorithm is that it will not produce correct results when the answer should be between MAXINT/2n and MAXINT. For that, you actually need to take advantage of what you were attempting to do:
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;
}
}
x = x * y
is the same asx *= y
but your expressions do not have this form. There is a division in there.x = x * y / z
is not the same asx *= y / z
. The order of operations is different – Jeffryjeffy/
is integer division, then there's a difference betweena * (b /c)
and(a * b) / c
, because of how the remainder is thrown away – Tarau64
, so this is integer division. (The function arg is au64
by reference for no apparent reason or benefit, so*n
dereferences it to get a u64.) – Openworkx = x * (*n + i) / i;
tox *= (*n + i); x /= i;
– ObriennCr(2*n,n)
, the number of unordered combinations in which n elements may be drawn (without replacement) from a set of 2n – Obrien