【问题标题】:Remainder operator in c89 and c99c89 和 c99 中的余数运算符
【发布时间】:2012-11-03 10:29:55
【问题描述】:

c99 标准规定模运算的结果与第一个操作数的符号相同。所以-9 % 7 = -29 % -7 = 2

我在一本书中读到,c89 标准取决于实现。所以-9 % 7 可以产生-2<strong>5</strong>-9 / 7 的余数是多少5

【问题讨论】:

标签: c c99 c89


【解决方案1】:

考虑两个数字ab

q=a/b 和余数r=a%b 满足方程a == q*b + r

-9 % 7 产生 5 的 C89 (假设)实现是其中 -9 / 7 计算为 -2 的实现。

数学(欧几里得)除法将r 限制为正数且小于b。 C99 将其限制为与a 相同的符号,并且严格在-bb 之间。 这只是一个约定俗成的问题。

【讨论】:

  • 如果整数除法不截断而是“向下舍入”(向-无穷大方向),那么这是合理的,不是吗?
  • @H2CO3 我在一个静态分析器上工作,其中一组可能的值可以总结为一致性信息(例如:“在这个程序的这一行中,我们知道x 的所有值都是等于 1 模 3”)。该分析器使用欧几里得除法,因为它具有最好的代数特性,但我不止一次抱怨 C99(实际上是处理器)易于实现但代数较少的选择。
  • 我明白了,但是 1. 我认为抱怨标准没有多大意义,它的编写是为了易于实施(否则你会如何解释所有未定义的行为?) 和 2. 对我来说,允许这样做似乎是合乎逻辑的,我认为强制整数除法向 0 舍入不是一个好主意。
  • @H2CO3 我认为您的第 1 点和第 2 点解释了 C89 中的选择(他们试图让每个人都开心)。在 C99 中,他们一定已经看到并意识到 每个 硬件实现都在进行截断,因此标准不妨这样指定除法。截断除法更容易在硬件中实现,因为结果的符号和绝对值可以并行计算。
  • @H2CO3 因为在尝试编写 C 程序时,不能假设除法以一种或另一种方式工作是很痛苦的。更极端的立场是“为什么要在标准中指定划分?为什么不将其保留为(实际上)所有编译器都会拥有的特定于编译器的扩展?”。答案是,像 C 这样的语言标准是在允许实现余地和允许程序员在没有在编译时检测除法的行为。
【解决方案2】:

% 运算符定义为:

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

所以

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

% 作为余数运算符

如果/0 舍入(如C99):

-9 % 7 == -2

你有-9 / 7 == -1 所以%-2 因为

-9 % 7 == -9 - (-9 / 7 * 7) + 9 == -9 + 7 == -2 

% 作为模运算符

如果/ 向负无穷大舍入:

-9 % 7 == 5

你有-9 / 7 == -2 所以%5

-9 % 7 == -9 - (-9 / 7 * 7) + 9 == -9 + 14 == 5

【讨论】:

  • 如果 / 向负无穷大舍入 从 C99 开始,标准禁止这种行为,对吧?
猜你喜欢
  • 2017-05-23
  • 2011-01-08
  • 2011-05-27
  • 2011-01-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多