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