【问题标题】:% (mod) explanation% (mod) 解释
【发布时间】:2012-04-21 08:18:36
【问题描述】:

今天我在用C#写一个程序,我用%来计算一些索引...我的程序没有工作,所以我调试它,我意识到“% " 不像我知道的其他程序语言那样工作。

例如:

在 Python 中,% 返回如下值:

for x in xrange (-5, 6):
     print x, "% 5 =", x % 5

-5 % 5 = 0
-4 % 5 = 1
-3 % 5 = 2
-2 % 5 = 3
-1 % 5 = 4
0 % 5 = 0
1 % 5 = 1
2 % 5 = 2
3 % 5 = 3
4 % 5 = 4
5 % 5 = 0

在 C# 中:

for (int i = -5; i < 6; i++)
{
    Console.WriteLine(i + " % 5 = " + i % 5);
}

-5 % 5 = 0
-4 % 5 = -4
-3 % 5 = -3
-2 % 5 = -2
-1 % 5 = -1
0 % 5 = 0
1 % 5 = 1
2 % 5 = 2
3 % 5 = 3
4 % 5 = 4
5 % 5 = 0

是我做错了什么还是% 没有正常工作?

【问题讨论】:

  • 在 C 派生语言中,% 不是取模运算符。它是 remainder 运算符。 Eric Lippert explains.
  • @RaymondChen 这看起来像是一个答案,而不是评论。不过,如果你愿意,我可以投票。
  • 如何在 C# 中使用取模运算符?
  • Wolfy - 如果值为负,则加 5。
  • @Wolfy c = a % b; if (c &lt; 0) { c += b; } return c;

标签: c# math operators modulo


【解决方案1】:

正如 cmets 中所解释的,不同的行为是设计使然。不同的语言只是赋予% 运算符不同的含义。

你问:

如何在 C# 中使用取模运算符?

您可以自己定义一个模数运算符,其行为方式与 Python % 运算符相同:

int mod(int a, int n)
{
    int result = a % n;
    if ((result<0 && n>0) || (result>0 && n<0)) {
        result += n;
    }
    return result;
}

【讨论】:

  • 您的代码给出了不正确的结果,例如 mod(-5, 5) == 5。有关工作示例,请参阅answer
  • @Drake @DavidHeffernan 我修复了这个答案代码中的错误。问题是它应该检查result 的值,而不是a 的值。
【解决方案2】:

modular arithmetic 中,根据模数定义。换句话说,在模 m 算术中,一个数 n 等价于(读作:相同)n + m em>, n - m, n + 2m, n - 2m

一个定义了 m 个“篮子”,每个数字都在其中一个(并且只有一个)中。

示例:可以说“现在是下午 4:30”,也可以说“现在是 16:30”。两种形式的含义完全相同,但是是不同的表示

因此,Python 和 C# 结果都是正确的!这些数字在您选择的模 5 算术中相同。例如,返回 (5, 6, 7, 8, 9) 也是数学上正确的。有点奇怪。

至于表示的选择(也就是负数如何表示的选择),这只是两种语言设计选择不同的一个例子。

然而,这根本不是 % 运算符在 C# 中实际所做的。 % 运算符不是规范模运算符;它是余数运算符。 A % B 运算符实际上回答了“如果我使用整数运算将 A 除以 B,余数是多少?”的问题

——What's the difference? Remainder vs Modulus by Eric Lippert


快速 sn-p 获取规范模数:

return ((n % m) + m) % m;

测试实现:

单声道/C#

machine:~ user$ cat mod.cs
using System;

public class Program
{
    public static void Main (string[] args)
    {
        Console.WriteLine(Mod(-2, 5));
        Console.WriteLine(Mod(-5, 5));
        Console.WriteLine(Mod(-2, -5));
    }

    public static int Mod (int n, int m)
    {
        return ((n % m) + m) % m;
    }
}

machine:~ user$ mono mod.exe
3
0
-2

Python

machine:~ user$ cat mod.py
print -2%5;
print -5%5;
print -2%-5;

machine:~ user$ python mod.py
3
0
-2

【讨论】:

  • -2 和 -5 的“规范模数”是什么?您的程序给出-2,但我认为您打算给出非负面结果。想再试一次吗?
  • @EricLippert 它没有。它分别返回 3 和 0。查看我的编辑。
  • 我向你保证,你的 sn-p 说 -2 和 -5 的规范模数是 -2。试试看:class P { static void Main() { int n = -2, m = -5; System.Console.WriteLine(((n%m)+m)%m)); } } 运行它,你会得到 -2 打印出来。如果您的意图是规范模数为非负数,那么您未能实现您的意图。想再试一次吗?
  • @Eric 啊,明白了! -5 是模数,而不是另一个输入......好吧,这仍然与 python 一致,不过:python -c 'print -2%-5;' 返回-2。我认为这就是 OP 所期待的。
  • 对于正确处理负除数的版本,请参阅此答案stackoverflow.com/a/10065670/4441547 这可能相当罕见,但对于大多数用例而言,上述答案工作正常。
【解决方案3】:

两个答案都是正确的。虽然我个人认为“总是积极的”更有意义。

你可以定义你自己的模数函数,它只给出这样的肯定答案:

int mod(int a, int n) {
    return ((a%n)+n) % n;
}

【讨论】:

  • mod(-5, 2) 返回什么?
  • 该死...好吧,让我再试一次。
  • mod(-2, -5) 返回 -2。您说它应该始终返回正值,但是有些输入会导致它返回负值。这可以接受吗?是预期的吗?
  • 我发现这样写更有效:int c = a % b; if (c &lt; 0) { c += b; } return c; 尽管请注意它不考虑负除数
  • @EricLippert 理论上它应该在 0 和第二个参数之间返回(所以如果除数是负数,那么它应该是负数,当除数为正时它应该是正数,不管被除数的符号如何)但是负除数是非常罕见。
猜你喜欢
  • 2017-10-21
  • 2021-05-03
  • 1970-01-01
  • 2020-11-05
  • 1970-01-01
  • 1970-01-01
  • 2015-03-23
  • 2012-11-12
  • 2012-12-16
相关资源
最近更新 更多