当我在Objective-C中进行模运算时,我得到的结果有点吓坏了。 -1%3出来是-1,这是不正确的答案:根据我的理解,它应该是-2 -2%3出现-2,这也是不正确的:它应该是1.Objective-C中的Modulo运算符返回错误结果
除了%运算符以获得正确的结果之外,还有另外一种方法吗?
当我在Objective-C中进行模运算时,我得到的结果有点吓坏了。 -1%3出来是-1,这是不正确的答案:根据我的理解,它应该是-2 -2%3出现-2,这也是不正确的:它应该是1.Objective-C中的Modulo运算符返回错误结果
除了%运算符以获得正确的结果之外,还有另外一种方法吗?
带负数的Modulo并不像您想象的那样直截了当。请参阅http://mathforum.org/library/drmath/view/52343.html
Objective-C是C99的超集,而C99的定义a % b
在a
为负数时为负数。另见the Wikipedia entry on the Modulo operation和this StackOverflow question。
类似于(a >= 0) ? (a % b) : ((a % b) + b)
(尚未经过测试,可能有不必要的括号)应该会给你想要的结果。
太棒了!它对我很有帮助,但是我记录了两种导致我错误的情况:(1)-n mod n给出了n而不是0.(2)将它定义为宏时,有些括号中出现混淆。我最终这样做: #define模块(a,b)(a> = 0 || - (a)==(b))? (a)%(b):((a)%(b)+ b) – kahlo 2013-08-25 20:10:49
ANSI C99 6.5.5乘operators-
6.5.5.5:在操作者/
的结果是由第二所述第一操作数的除法的商;余下的是%
运算符的结果。在两种操作中,如果第二个操作数的值为零,则行为未定义。
6.5.5.6:当整数分开时,/
算子的结果是舍弃任何小数部分(* 90)的代数商。如果商a/b
可表示,则表示(a/b)*b + a%b
应等于a
。
* 90:这通常称为“向零截断”。
您正在考虑的模行为的类型称为“模运算”或“数论”样式模/余数。使用模运算符的模算术/数论定义,得到否定结果是不合理的。这显然不是C99定义和使用的模行为的风格。 C99的方式没有什么“错误”,这不符合你的期望。 :)
一个明确的功能,会给你正确的答案是在年底,但首先,这里所讨论的的一些其他的想法解释:
其实,(a >= 0) ? (a % b) : ((a % b) + b)
只会导致如果负数a在b的一个倍数内,则为正确答案。
换句话说:如果您想查找:-1%3,那么当然,(a >= 0) ? (a % b) : ((a % b)+ b)
将起作用,因为您在((a % b) + b)
的末尾加回。
-1 % 3 = -1
and -1 + 3 = 2
,这是正确的答案。
但是,如果你尝试它= -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分成整数,您会得到意想不到的答案。当然,这意味着你的结果也将是一个浮动。它将是一个写成浮点数的整数,如2.000000,因此您可能希望将整个答案转换回整数。
(int) (a - floor((float) a/b)*b)
斯宾塞,有一种简单的方法来思考mods(它在数学中定义的方式,而不是编程)。它实际上是相当简单:
采取所有的整数:
...- 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,,1 ,2,3 ,4,5,6 ,7,8,9 ...
这些都是当除以3具有一个零剩余的数字,即,这些都是修改为零的那些。
现在让我们把这整个组合起来。
...- 9,-8,-7,-6,-5,-4,-3,-2,-1,0,,2,3,4 ,5, 6,,8,9 ...
这些都是当除以3具有一为1其余部分的数字,即,这些都认为国防部为1
现在让我们移的那些这整个组合再次由一个。
...- 9,-8,-7,-6,-5,-4,-3,-2,-1,0,1,2 ,3,4,5 , 6,7,8 ,9 ...
这些都是当除以3即有2个剩余数量,即这些都认为国防部于2
你的那些注意,在每种情况下,选中的数字间隔为3.因为我们考虑模3,所以我们总是取每三位数。(如果我们在做模5,我们会每五位取一个数)。
所以,你可以将这种模式向后转换为负数。只需保持3的间距。你会得到这三个相同级(一种特殊类型的等价类,因为他们是所谓的在数学):
... -9,-8,-7,-6,-5,-4,-3 ,-2,-1,,1,2,3 ,4,5,6 ,7,8,9 ...
...- 9,-8,-7,-6,-5 ,-4,-3,-2 ,-1,0,,2,3,4 ,5,6,7 ,8,9 ...
...- 9,-8,-7 ,-6,-5,-4 ,-3,-2,-1 ,0, 1,,3,4,,6,7,,9 ...
所有这些等效数字的标准数学表示法是使用该类的残基,这意味着取最小的非负数。
所以通常情况下,当我想MODS的,我处理的是一个负数,我只是觉得先后连连加模数,直到我得到的第一个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,这是数学家通常使用的形式。
我有同样的问题,但我解决了它!您只需检查数字是正数还是负数,如果数字是负数,则需要再添加一个数字:
//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);
}
希望对您有所帮助!答:
好奇,如果任何这些答案重新模数你正在寻找 – kris 2011-11-10 16:02:42
使用frem(a,b) - 你期待的模数(这是标准数学中使用的那种)在编码中被称为“余数” 。 C有fmod()和frem(),你使用的是mod(又名“%”),你需要使用rem。数学模数===代码中的剩余(rem)。哑巴,我知道。 – 2016-07-07 07:36:05
它引起了我的注意,frem(a,b)仅在GNU C中,没有被带入Obj-C。相当于这样:'a-b * floor((float)a /(float)b)' – 2016-07-07 07:44:46