在C#中,我该如何计算整数的除法和取模?

102
在C#中如何计算整数的除法和取模?

18
这可能太基础了,但它是一个真正的问题... - Aryabhatta
3
一个相关的帖子和一篇必读的博客,解释了为什么在C#中%运算符不是模运算符。 - RBT
6个回答

144

这是来自MSDN文档的答案。

当你除以两个整数时,结果总是一个整数。例如7 / 3的结果是2。要确定7 / 3的余数,请使用余数运算符 (%).

int a = 5;
int b = 3;

int div = a / b; //quotient is 1
int mod = a % b; //remainder is 2

12
%返回余数,而不是模数(正如您所指出的)。 它们不是同一件事,并且在处理不寻常情况(例如负索引)时可能会导致问题。 但是,当只需要查找弱正索引器的每第10次迭代时,可以像模运算符一样使用它。也许您可以解释一下如何计算真正的模数? - Cor_Blimey
1
没错,我读过像这样的帖子,而且在我的应用程序中也遇到过问题 :) - apocalypse
1
如果你不打算使用它们,那么声明ab的目的是什么呢? :D - leviathanbadger
1
也许用户(就像我一样)正在寻找一个DivRem函数,所以这个问题可能并不像乍一看那么简单。谢谢 @danodonovan - Tancredi
1
答案并不像这个回答所声称的那样简单,正如其他人也指出的那样,它可能会导致难以调试的错误。 请参见https://dev59.com/pGkw5IYBdhLWcg3wMHum。 - SansWit
显示剩余5条评论

104

还有Math.DivRem函数。

quotient = Math.DivRem(dividend, divisor, out remainder);

3
在我看来,这应该是正确的答案,因为它提供了商和余数在一个函数中。我不确定哪种方法更有效(使用“a / b”获取商,然后使用“a%b”获取余数或使用Math.DivRem),但这种方法确实更易于阅读(在我的情况下,我需要知道商和余数)- 谢谢! - Igor
2
@Igor 谢谢,当最初的问题得到回答时,这个函数还不存在!然而,该函数的存在使得 as-cii 对于检查文档的评论看起来有点傻.... :) - danodonovan
11
为了避免混淆,Math.DivRem 函数并不会一次性计算除法和取模运算。它只是一个辅助函数,其源代码如下:public static int DivRem(int a, int b, out int result) { result = a%b; return a/b; } - NightElfik
11
@NightElfik 实现方式以后可能会改变,对于运行时识别方法调用进行优化要比离散的 divrem 指令更容易。 - kbolino
9
@kbolino 这是一个很好的预测,因为它已经改变,至少在.NET Core中,现在采用除法和减法运算。并且RyuJIT计划进行进一步的优化,使用单个x86除法指令,虽然JIT的更改也应该可以检测到分别使用%/运算符的情况。 - Bob

17

趣闻!

'模除'运算被定义为:

a % n ==> a - (a/n) * n

参考资料:模运算

因此,您可以自己编写代码实现模运算,但这将比内置的%运算符慢得多:

public static int Mod(int a, int n)
{
    return a - (int)((double)a / n) * n;
}

编辑:哇,我最初说错了很多话,在此感谢@joren指出。

现在我依赖于C#中除法和强制转换为整数等价于 Math.Floor(即会舍去小数部分)这一事实,但是“真正”的实现应该是:

public static int Mod(int a, int n)
{
    return a - (int)Math.Floor((double)a / n) * n;
}

实际上,您可以通过以下方式看到%和“真模数”之间的差异:

var modTest =
    from a in Enumerable.Range(-3, 6)
    from b in Enumerable.Range(-3, 6)
    where b != 0
    let op = (a % b)
    let mod = Mod(a,b)
    let areSame = op == mod
    select new 
    { 
        A = a,
        B = b,
        Operator = op, 
        Mod = mod, 
        Same = areSame
    };
Console.WriteLine("A      B     A%B   Mod(A,B)   Equal?");
Console.WriteLine("-----------------------------------");
foreach (var result in modTest)
{
    Console.WriteLine(
        "{0,-3} | {1,-3} | {2,-5} | {3,-10} | {4,-6}", 
        result.A,
        result.B,
        result.Operator, 
        result.Mod, 
        result.Same);
}

结果:

A      B     A%B   Mod(A,B)   Equal?
-----------------------------------
-3  | -3  | 0     | 0          | True  
-3  | -2  | -1    | -1         | True  
-3  | -1  | 0     | 0          | True  
-3  | 1   | 0     | 0          | True  
-3  | 2   | -1    | 1          | False 
-2  | -3  | -2    | -2         | True  
-2  | -2  | 0     | 0          | True  
-2  | -1  | 0     | 0          | True  
-2  | 1   | 0     | 0          | True  
-2  | 2   | 0     | 0          | True  
-1  | -3  | -1    | -1         | True  
-1  | -2  | -1    | -1         | True  
-1  | -1  | 0     | 0          | True  
-1  | 1   | 0     | 0          | True  
-1  | 2   | -1    | 1          | False 
0   | -3  | 0     | 0          | True  
0   | -2  | 0     | 0          | True  
0   | -1  | 0     | 0          | True  
0   | 1   | 0     | 0          | True  
0   | 2   | 0     | 0          | True  
1   | -3  | 1     | -2         | False 
1   | -2  | 1     | -1         | False 
1   | -1  | 0     | 0          | True  
1   | 1   | 0     | 0          | True  
1   | 2   | 1     | 1          | True  
2   | -3  | 2     | -1         | False 
2   | -2  | 0     | 0          | True  
2   | -1  | 0     | 0          | True  
2   | 1   | 0     | 0          | True  
2   | 2   | 0     | 0          | True  

现在我依赖于C#中整数除法等同于Math.Floor(即,它会舍弃小数部分)这一事实,但实际上并非如此。整数除法向零舍入,而Math.Floor向负无穷大舍入。 - Joren
@Joren 抱歉,不行 - 试着运行这段代码:Enumerable.Range(0, 10).Select(x => (double)x / 10.0).Select(x => (int)x).ToList().ForEach(x => Console.WriteLine(x)); - 输出将全部为0。 - JerKimball
2
首先,我要谈论的是整数除法。如果你进行浮点数除法然后转换为整数,结果无关紧要(即使它给出相同的结果)。其次,我不确定为什么您希望在将0到9之间的整数除以10并截断为整数部分后得到除0以外的任何内容。如果结果为1,则会向零舍入或向正无穷舍入。第三,对于正数,向零舍入和向负无穷舍入之间没有任何区别,因此您甚至没有解决问题。 - Joren
Math.Floor(-10.0 / 3.0)-10 / 3 不是同一件事情。 - Joren
@joren,我明白这里的误会了 - 不,我不是执行整数除法,我是执行双精度除法,然后将结果强制转换为整数 - 这是非常不同的。 - JerKimball
显示剩余2条评论

15

使用/运算符进行除法:

result = a / b;

使用%运算符进行模除:

result = a % b;

1
+1:方便地省略类型使其成为更好的答案 :-) 我相信在4.0中使用System.Numeric.BigInteger也可以实现。 - Aryabhatta
5
如Cor_Blimey所说,它返回的是余数而不是模数。例如:(-5 % 3) == -2 [C#],-5 mod 3 = 1 [wolframalpha.com]。 - apocalypse
2
注意:模运算不同于模数。 模运算是余数,模数是绝对值。 - Ryan

0

余数:a % b 例子:5 % 3 = 2

除法:

当两个变量都是整数时:5/3 = 1

当需要整数结果而输入为小数时:Math.Floor(5/3)

如果不想使用Math类:5/3 - (5%3)/3


-5
从用户读取两个整数。然后计算/显示余数和商。
// When the larger integer is divided by the smaller integer
Console.WriteLine("Enter integer 1 please :");
double a5 = double.Parse(Console.ReadLine());
Console.WriteLine("Enter integer 2 please :");
double b5 = double.Parse(Console.ReadLine());

double div = a5 / b5;
Console.WriteLine(div);

double mod = a5 % b5;
Console.WriteLine(mod);

Console.ReadLine();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接