【问题标题】:Why 7%-5 gives 2 but -7%5 gives -2? Shouldn't it be -2 in both cases? [duplicate]为什么 7%-5 给出 2 而 -7%5 给出 -2?在这两种情况下都不应该是-2吗? [复制]
【发布时间】:2013-05-16 10:43:38
【问题描述】:

请解释以下原因,因为数学上这两种情况的正确答案都是-2

int a=7%-5; //Assigns 2 to a
int a=-7%5;  //Assigns -2 to a

代码是 C 语言。

【问题讨论】:

    标签: c modulo


    【解决方案1】:

    7 / -5 = -1 余数为2,因为-1 * -5 + 2 = 5 + 2 = 7

    -7 / 5 = -1 余数为-2,因为-1 * 5 + (-2) = -5 - 2 = -7

    C++ 中的% 是余数运算符(对于正数,它用作数学模运算符)。

    【讨论】:

      【解决方案2】:

      因为在大多数 C 实现中,整数除法截断并且不会向负无穷大舍入。您的实现似乎也是其中之一。

      a % b = a - (a / b) * b
      

      所以

      7 % (-5) = 7 - (7 / -5) * (-5)
      

      这是

      7 % (-5) = 7 - (-1) * (-5) = 7 - 5 = 2
      

      【讨论】:

      • 这是定义的实现,因此它可能因 C 编译器而异。
      • @IlmoEuro 对,刚刚找到this,会更新答案。
      • 从 C99 开始,需要整数除法才能截断。
      【解决方案3】:

      在 C 90 或 C++ 98 标准中没有指定负数的模数应该是什么符号。任何一个都可以接受。它在 C 99 和 C++ 2011 中被定义为与被除数具有相同的符号。

      有关模数和余数之间差异的讨论,请参阅这篇文章:

      还有这篇维基百科上的文章,它引用了标准状态。

      【讨论】:

        【解决方案4】:

        答案不是数学的,而是常规的。理论上,模运算符总是有两种可能的结果,负数和正数。

        7 % 5
        

        2-3

        在数学中,大多数情况下使用积极的结果。在取决于编程语言的编程中。

        原始 C 没有指定使用哪一个。使用正数,您总是得到正模数;对于负数,结果取决于所使用的编译器。

        C-99 指定模数的结果应该与被除数具有相同的符号。这解释了你观察到的行为。

        您可以在不同的编程语言here看到模运算符的结果。

        【讨论】:

          【解决方案5】:

          规则是r = a - (a/b) * b

          所以

          2 = 7 - (7/-5)*(-5) // note: 7/-5 is -1

          【讨论】:

            【解决方案6】:

            模运算负值在 IT 中没有单一的定义。 共有三种不同的算法:

            • 截断除法
            • 地板分区
            • 欧几里得除法

            当操作数为正时提供相同的结果,但当它们为负时提供不同的结果。

            More information

            许多实现使用截断除法,其中商为 由截断 q = trunc(a/n) 定义,换句话说,它是第一个 从精确有理商到 0 方向的整数,以及 余数为 r=a - n q。非正式地说,商是 “向零四舍五入”,因此余数具有相同的符号 作为股息。

            Knuth 描述了底除法,其中商定义为 底函数 q=floor(a/n) 余数为 r

            r = a - nq = a - n \left\lfloor {a \over n} \right\rfloor.
            

            这里的商总是向下舍入(即使它已经 负数),余数与除数的符号相同。

            Raymond T. Boute 引入了欧几里得定义,即 其中余数始终为正或 0,因此为 与除法算法一致(见欧几里得除法)。这 定义在表中标记为“始终为正”。设 q 为 a和n的整数商,则:

            在 C 中,问题在于算法是实现定义的, 所以你需要为负数滚动你自己的模运算 如果你希望你的程序是可移植的。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2011-05-20
              • 1970-01-01
              • 2022-11-19
              • 2012-10-21
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2020-12-03
              相关资源
              最近更新 更多