在使用Objective-C进行模运算时,我对结果感到有些惊讶。-1 % 3的结果是-1,这不是正确的答案:根据我的理解,它应该是2。-2 % 3的结果是-2,这也是不正确的:它应该是1。
除了%运算符,是否还有其他方法可以得到正确的结果?
在使用Objective-C进行模运算时,我对结果感到有些惊讶。-1 % 3的结果是-1,这不是正确的答案:根据我的理解,它应该是2。-2 % 3的结果是-2,这也是不正确的:它应该是1。
除了%运算符,是否还有其他方法可以得到正确的结果?
Objective-C是C99的超集,而C99将a % b
定义为当a
为负数时为负数。另请参见维基百科关于模运算的条目和这个StackOverflow问题。
像(a >= 0) ? (a % b) : ((a % b) + b)
这样的代码(尚未经过测试,可能有不必要的括号)应该给您想要的结果。
#define module(a, b) (a >= 0 || -(a) == (b)) ? (a)%(b) : ((a)%(b) + b)
- kahlo...-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, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ...
所有等价数字的标准数学表示法是使用该类的“余数”,这意味着取最小的非负数。
因此,通常情况下,当我考虑模数并处理负数时,我只想着不断添加模数,直到获得第一个0或正数:
如果我们使用模3,则对于-1,只需添加3次:-1 + 3 = 2。 对于-4,添加2次3,因为一次不够。如果我们添加+3一次,我们得到-4 + 3 = -1,仍然是负数。所以我们将再次添加+3:-1 + 3 = 2。
让我们尝试一个更大的负数,如-23。如果您不断添加+3,则会得到:
-23,-20,-17,-14,-11,-8,-5,-2,1。我们得到了一个正数,所以我们停止。余数为1,这是数学家通常使用的形式。
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方式没有什么“问题”,只是不符合您的预期。 :)
//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);
}
先来解释一些其他讨论过的想法,最后再给出一个明确的函数来得到正确的答案:
实际上,只有当负数 a 在 b 的一个倍数范围内时,(a >= 0) ? (a % b) : ((a % b)+ b)
才能得出正确的答案。
换句话说:如果你想要找到 -1 % 3 的结果,那么这个公式可以工作,因为你在 ((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
** 注意!确保保留(float)转换。否则,它将把a/b作为整数除以,对于负数,您将得到意外的答案。当然,这意味着您的结果也将是一个浮点数。它将是一个写成浮点数的整数,例如2.000000,因此您可能希望将整个答案转换回整数。
(int) (a - floor((float) a/b)*b)
a-b*floor((float)a/(float)b)
。 - Albert Renshaw