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

Posted

技术标签:

【中文标题】如何在 C# 中计算整数的除法和模数?【英文标题】:How can I calculate divide and modulo for integers in C#? 【发布时间】:2011-07-19 23:26:03 【问题描述】:

【问题讨论】:

这可能太基本了,但这是一个真正的问题...... 一个相关的post 和必读的blog 说明为什么% 运算符不是 C# 中的模运算符。 【参考方案1】:

这是来自MSDN documentation的答案。

当你将两个整数相除时,结果总是一个整数。例如,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

【讨论】:

% 返回余数,而不是模数(正如您指出的那样)。它们不是同一件事,并且在处理异常情况(例如负索引)时可能会导致问题。但是,它可以像模运算符一样在仅查找时使用,例如,弱正索引器的每 10 次迭代。或许你能解释一下如何计算真正的模数? 没错,我读过这样的帖子,但我的应用程序有问题:) ...如果您不打算使用它们,那么声明ab 到底有什么意义? :D 也许用户(像我一样)正在搜索 DivRem 函数,所以这个问题可能不像乍一看那么简单。谢谢@danodonovan 答案并不像其他人所指出的那样简单,并且可能导致难以调试的错误。见https://***.com/questions/10065080/mod-explanation【参考方案2】:

还有Math.DivRem

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

【讨论】:

在我看来这应该是正确的答案,因为它在一个函数中提供了商和余数。我不确定哪种方法性能更好(使用“a / b”来获得商,然后使用“a % b”来获得余数或 Math.DivRem),但这种方法肯定更好读(在我的情况下,我需要知道商和余数)-谢谢! @Igor 谢谢,回答原始问题时,此功能不存在!然而,该函数的存在确实让 as-cii 关于检查文档的评论看起来有点傻...... :) 为了避免混淆,Math.DivRem 不会一次计算 div 和 mod。它只是一个辅助函数,它的源代码是:public static int DivRem(int a, int b, out int result) result = a%b; return a/b; @NightElfik 未来的实现可能会发生变化,运行时更容易识别方法调用以进行优化,而不是不相交的divrem 指令 @kbolino 这是一个很好的预测,因为it has changed 至少在 .NET Core 中可以进行除法运算。 RyuJIT 计划进一步优化以使用单个 x86 div 指令,但诚然,如果单独使用 JIT 更改也应该检测到 %/ 运算符。【参考方案3】:

有趣的事实!

“模数”运算定义为:

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

参考:Modular Arithmetic

所以你可以自己滚动,虽然它会比内置的 % 运算符慢得多:

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 抱歉,不行 - 尝试运行这个:Enumerable.Range(0, 10).Select(x => (double)x / 10.0).Select(x => (int)x).ToList().ForEach(x => Console.WriteLine(x)); - 全为 0 首先,我说的是整数除法。如果您进行浮点除法然后转换为整数会发生什么是无关紧要的(即使它给出相同的结果)。其次,我不确定为什么你会期望 0 到 9 之间的整数在除以 10 并截断为整数部分后给出除 0 以外的任何值。如果结果为 1,则将 远离 从零或向 无穷大舍入。第三,对于正数,向零四舍五入和向负无穷大四舍五入之间没有任何区别,因此您甚至没有解决这个问题。 Math.Floor(-10.0 / 3.0)-10 / 3 不是相同的东西。 @joren 啊,我看到这里断开连接 - 不,我没有执行 integer 除法,我正在执行双除法,然后将结果转换为整数 - 非常不同。【参考方案4】:

使用/ 运算符执行除法:

result = a / b;

使用% 运算符完成模除:

result = a % b;

【讨论】:

+1:方便地省略类型使其成为更好的答案 :-) 我相信这也适用于 4.0 中的 System.Numeric.BigInteger。 % --> 正如 Cor_Blimey 所说,它返回余数而不是模数。例如:(-5 % 3) == -2 [C#], -5 mod 3 = 1 [wolframalpha.com]。 注意:模数与模数不同。模数是余数,模数是绝对值。【参考方案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();

【讨论】:

以上是关于如何在 C# 中计算整数的除法和模数?的主要内容,如果未能解决你的问题,请参考以下文章

什么是疯狂大整数除法的最快算法?

如何对整数除法的结果进行四舍五入?

NumPy中模数(%)和地板除法(//)之间的区别?

如何解决使用 Z3 产生整数结果的整数除法?

如何在 Java 中舍入整数除法并获得 int 结果? [复制]

无论结果如何,支持除以零的最快整数除法是啥?