模数运算符更改

时间:2010-08-29 13:40:11

标签: c++ modulus

  

$ 5.6 / 4在C ++ 03状态中 - “如果两者都有   操作数是非负的   余数是非负的;如果不是,则为   其余的标志是   实现定义 74)

注74是

  根据正在进行的工作   修改ISO C,首选   整数除法算法   遵循ISO中定义的规则   Fortran标准,ISO / IEC 1539:1991,   其中商始终存在   向零舍入。

C ++ 0x状态 -

  

$ 5.6 / 4-“对于积分操作数,/运算符产生代数商,丢弃任何小数部分; 79 如果商a / b可在结果类型中表示,{{1等于a。

注79说

  

这通常被称为截断为零。

所以我有两个问题:

  • 有人可以解释这个“截断为零”的概念吗?

  • 具有负操作数的模数是否在C ++ 0x中定义了行为?

3 个答案:

答案 0 :(得分:6)

截断为零意味着通过选择接近零的下一个整数将实数转换为整数。等价地,您将数字写下来,并忽略小数点后的所有内容,无论数字是正数还是负数。

考虑11/4 = 2.75 - 如果将此截断为零,则得到2。

考虑-11/4或11 / -4 = -2.75 - 如果将此截断为零,则得-2。

对于某些数学运算来说,重要的是(a / b)* b + a%b == a。如果我们必须保持这个等式,并且我们也接受整数除法截断为零,那么我们可以推导出%运算符的操作如下:

a == 11, b == 4:
a/b == 2, 2*4 + a%b == 11, therefore a%b == 3.

a == -11, b == 4:
a/b == -2, -2 * 4 + a%b == -11, therefore a%b == -3.

a == 11, b == -4:
a/b == -2, -2 * -4 + a%b == 11, therefore a%b == 3.

a == -11, b == -4:
a/b == 2, 2 * -4 + a%b == -11, therefore a%b == -3.

一开始可能会让人感到困惑,但C ++ 0x使用等式a%b来定义(a/b)*b + a%b == a运算符的行为。该等式甚至适用于负数,因此a%b定义为负数。

答案 1 :(得分:3)

a)考虑(±5)/(±3) -> ±1。在数字行上:

  (-5)/3                                     5/3
     5/(-3)                               (-5)/(-3)
      =                                       =
    -1.66 --> -1                       1 <-- 1.66
       v       v                       v       v
-  +  -  -  -  +  -  -  -  +  -  -  -  +  -  -  -  +  -
   |           |           |           |           |
  -2          -1           0           1           2

因此,舍入是零。

b)是的。由于a/b现已为所有abb == 0除外)和(a/b)*b + a%b == a定义,因此a%b只有一个唯一解决方案,因此%运算符也适用于所有abb == 0除外)。

答案 2 :(得分:1)

a)“截断为零”只是意味着任何小数部分被砍掉。截断的数字始终至少与原始数字一样接近0,并且通常比原始数字更接近。

这在负数中最为明显,但目标是使用/%使用负数时不那么棘手(因为目前,任何实现都可以处理它,但是他们选择)。 -7/4可以被认为是两种方式:-2,余数为1,或-1,余数为-3。并且有编译器和处理器可以同时处理它。由于-7/4实际上是-1.75,“截断为零”会给你-1,所以后一种方式是标准的。

b)中 这就是它的样子。它始终是半定义的(“实现定义的”),但这似乎是尝试从一开始就定义标准内容。