当我在Objective-C中进行模运算时,我得到的结果让我有点吓坏了。 -1%3现在是-1,这不是正确的答案:根据我的理解,它应该是2. -2%3出现-2,这也是不对的:它应该是1.
除了%运算符之外,我还应该使用另一种方法来获得正确的结果吗?
答案 0 :(得分:7)
Objective-C是C99的超集,当a % b
为负时,C99将a
定义为否定。另请参阅the Wikipedia entry on the Modulo operation和this StackOverflow question。
像(a >= 0) ? (a % b) : ((a % b) + b)
这样的东西(尚未经过测试,可能有不必要的括号)应该可以得到你想要的结果。
答案 1 :(得分:3)
取所有整数:
...- 9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2,3,4,5,6,7,8 ,9 ......
现在让我们考虑3的倍数(如果你正在考虑 mod 3 )。让我们从0开始,正数为3:
...- 9,-8,-7,-6,-5,-4,-3,-2,-1, 0 ,1,2, 3 ,4,5, 6 ,7,8, 9 ......
这些是除以3时余数为零的所有数字,即这些都是mod为零的数字。
现在让我们将整个小组改为一个。
...- 9,-8,-7,-6,-5,-4,-3,-2,-1,0, 1 ,2,3, 4 ,5,6, 7 ,8,9 ...
这些是除以3时余数为1的所有数字,即这些都是mod为1的数字。
现在让我们再将整个小组改为一个。
... - 9,-8,-7,-6,-5,-4,-3,-2,-1,0,1, 2 ,3,4, 5 ,6,7, 8 ,9 ...
这些是除以3时余数为2的所有数字,即这些都是mod为2的数字。
您会注意到,在每种情况下,所选数字的间隔为3.我们总是采用每三个数字,因为我们正在考虑模3。(如果我们做模5,我们会采取每一个第五号)。
因此,您可以将此模式向后转换为负数。保持3的间距。你将获得这三个同余类(一种特殊类型的等价类,因为它们在数学中被称为):
... -9 , - 8,-7, -6 , - 5,-4, -3 , - 2 ,-1, 0 ,1,2, 3 ,4,5, 6 ,7,8, 9 ...
...- 9, -8 , - 7,-6, -5 , - 4,-3, -2 ,-1,0, 1 ,2,3, 4 ,5,6, 7 ,8,9 ......
...- 9,-8, -7 ,-6,-5, -4 , - 3,-2, -1 < / strong>,0,1, 2 ,3,4, 5 ,6,7, 8 ,9 ...
所有这些等价数字的标准数学表示是使用类的残差,这意味着取最小的非负数。
通常情况下,当我在思考mod并且我正在处理负数时,我只想到连续添加模数,直到我得到第一个0或正数:
如果我们正在使用mod 3,那么使用-1,只需添加3次:-1 + 3 = 2。 用-4,两次加3,因为一次是不够的。如果我们加+3一次,我们得到-4 + 3 = -1,这仍然是负数。所以我们再添加+3:-1 + 3 = 2。
让我们尝试一个更大的负数,比如-23。如果你继续增加+3,你会得到:
-23,-20,-17,-14,-11,-8,-5,-2,1。我们得到一个正数,所以我们停下来。残差为1,这是数学家通常使用的形式。
答案 2 :(得分:2)
ANSI C99 6.5.5乘法运算符 -
6.5.5.5:/
运算符的结果是第一个操作数除以第二个操作数的商; %
运算符的结果是余数。在这两个操作中,如果第二个操作数的值为零,则行为未定义。
6.5.5.6:当整数被分割时,/
运算符的结果是代数商,丢弃了任何小数部分(* 90)。如果商a/b
可表示,则表达式(a/b)*b + a%b
应等于a
。
* 90:这通常被称为“截断为零”。
您正在考虑的模数行为的类型称为“模数算术”或“数论”样式模/余数。使用模运算符的模运算/数论定义,得到否定结果是非感性的。这显然不是C99定义和使用的模数行为的风格。 C99方式并没有什么“错误”,这不是你所期待的。 :)
答案 3 :(得分:1)
负数的模数并不像你想象的那么简单。见http://mathforum.org/library/drmath/view/52343.html
答案 4 :(得分:1)
我有同样的问题,但我解决了!您需要做的就是检查数字是正数还是负数,如果数字为负数,则需要再添加一个数字:
//neg
// -6 % 7 = 1
int testCount = (4 - 10);
if (testCount < 0) {
int moduloInt = (testCount % 7) + 7; // add 7
NSLog(@"\ntest modulo: %d",moduloInt);
}
else{
int moduloInt = testCount % 7;
NSLog(@"\ntest modulo: %d",moduloInt);
}
// pos
// 1 % 7 = 1
int testCount = (6 - 5);
if (testCount < 0) {
int moduloInt = (testCount % 7) + 7; // add 7
NSLog(@"\ntest modulo: %d",moduloInt);
}
else{
int moduloInt = testCount % 7;
NSLog(@"\ntest modulo: %d",moduloInt);
}
希望有所帮助!甲
答案 5 :(得分:0)
最后会给出正确答案的显式函数,但首先,这里是对所讨论的其他一些观点的解释:
实际上,如果负数a在b的一个倍数范围内,(a >= 0) ? (a % b) : ((a % b) + b)
只能得到正确答案。
换句话说:如果你想找到:-1%3,那么确定(a >= 0) ? (a % b) : ((a % b)+ b)
会有效,因为你在((a % b) + b)
的最后添加了回来。
-1 % 3 = -1
和
-1 + 3 = 2
,这是正确答案。
但是,如果你尝试使用a = -4和b = 3,那么它将不起作用:
-4 % 3 = -4
但是
-4 + 3 = -1
。
虽然这在技术上也相当于2(模3),但我认为这不是你要找的答案。您可能期望规范形式:答案应该始终是介于0和n-1之间的非负数。
你必须加两次+3才能得到答案:
-4 + 3 = -1
-1 + 3 = 2
这是一种明确的方法:
a - floor((float) a/b)*b
**小心!确保你保持(浮动)施法。否则,它会将a / b除以整数,你会得到一个意外的答案。当然这意味着你的结果也是浮动的。它将是一个写为float的整数,如2.000000,因此您可能希望将整个答案转换回整数。
(int) (a - floor((float) a/b)*b)