对于三个 n 位有符号整数a
、b
、 和c
(例如 32 位),a * (b + c) == (a * b) + (a * c)
考虑到整数溢出,总是真的吗?
我认为这是与语言无关的,但如果不是,我对 Java 的答案特别感兴趣。
对于三个 n 位有符号整数a
、b
、 和c
(例如 32 位),a * (b + c) == (a * b) + (a * c)
考虑到整数溢出,总是真的吗?
我认为这是与语言无关的,但如果不是,我对 Java 的答案特别感兴趣。
是的,它成立,因为整数算术是有限环上的模算术。
你可以在这里看到一些理论讨论:https ://math.stackexchange.com/questions/27336/associativity-commutativity-and-distributivity-of-modulo-arithmetic
是的,这总是正确的。
这是一个有效的属性,因为您正在有效地进行算术模 2^32。Java 被签名的事实int
使事情稍微复杂化(这意味着您不能假设您通常在做与模运算等效的操作),但不会影响这个特定的分配属性。
一个思想实验是考虑使用重复加法来实现它,并考虑它溢出时会发生什么。由于进行加法的顺序不会影响int
s 的结果(即使有溢出),所以也不会以不同的顺序将乘法作为重复加法。而且由于int
乘法总是等价于重复加法,因此对于重新排序的乘法,结果也必须相同。量子点
分配性质适用于模算术;因为,对于相同的(无符号)位长度,固定位长度二进制补码整数算术与模算术同态,所以在使用二进制补码算术时分配属性成立。
更详细的解释可以在这里找到。
是的,它确实适用于 Java,包括溢出情况。(某些其他语言没有指定溢出行为,在这种情况下不做任何保证。)
对于有符号整数的 2 补码数学,问题归结为:
is (a*(b+c))%(2**32) === (a*b+a*c)%(2**32)
所以对于 2 的补码有符号整数数学,它总是正确的。
对于非 2 的补码有符号整数数学,我想这取决于如何处理溢出。如果它反映了模数学,那么它是真的。