【问题标题】:Integer division rounding with negatives in C++C++ 中带负数的整数除法舍入
【发布时间】:2008-11-26 06:06:28
【问题描述】:

假设a 和b 都是int 类型,而b 不为零。考虑在以下情况下执行a/b 的结果:

  1. a 和 b 都是非负数。
  2. a 和 b 都是否定的。
  3. 其中有一个是否定的。

在情况 1 中,结果向下舍入到最接近的整数。但是标准对案例 2 和案例 3 有什么规定?我在 Internet 上发现的一个旧草案表明它依赖于实现(是的,甚至是案例 2),但委员会倾向于使其始终“向零舍入”。有谁知道(最新)标准说什么?请仅根据标准来回答,而不是根据什么是有意义的,或者特定的编译器做了什么。

【问题讨论】:

  • 鉴于标准的 1200 页性质,令人难以置信的研究机会。我要给它一个快速的 grep 并放弃:)

标签: c++ rounding


【解决方案1】:

根据 2008 年 5 月的修订,

你是对的:

二元 / 运算符产生商,二元 % 运算符产生第一个表达式除以第二个表达式的余数。如果 / 或 % 的第二个操作数为零,则行为未定义;否则 (a/b)*b + a%b 等于 a。如果两个操作数都是非负数,则余数是非负数;如果不是,则余数的符号是​​实现定义的75)。

注释 75 说:

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

C++ 在这方面很有可能落后于 C。就目前而言,它是未定义的,但他们着眼于改变它。

我与 Stroustrup 在同一部门工作,并与委员会的一名成员一起工作。事情需要 AGES 才能完成,而且它无休止的政治化。如果这看起来很愚蠢,那可能是。

【讨论】:

  • 引用的语句是旧的。它可以追溯到 C++98 标准,指的是 C99 修订版。 C99 指定向零舍入,C++11 也是如此。
【解决方案2】:

作为其他答案的更新:

C++11 的最后一个草案 n3242 在大多数实际用途上与实际的 C++11 标准相同,在 5.6 第 4 点(第 118 页)中这样说:

对于整数操作数,/ 运算符产生代数商 丢弃任何小数部分; (见注释 80)

注释 80 状态(注意注释是非规范性的):

80) 这通常称为向零截断。

第 4 点继续说明:

如果商 a/b 在结果的类型中是可表示的, (a/b)*b + a%b 等于 a。

这可以表明要求a%b 的符号与a 的符号相同(当不为零时)。

【讨论】:

    【解决方案3】:

    只是一个评论。 C++ 标准的当前工作草案确实纠正了“实现定义”的问题,并要求截断为零。 Here 是委员会的网页,here 是草案。问题在第 112 页。

    【讨论】:

      【解决方案4】:

      有时我们需要退后一步,看看它的数学原理:

      给定 int x, int y

      如果 int i1 = x/y 并且 int i2 = x%y

      那么 y * i1 + i2 必须是 x

      所以这与标准无关,但可能只有一种方式。如果任何标准允许它以任何其他方式出现,那么标准是错误的,这意味着语言被破坏了。

      【讨论】:

      • 你说的是真的,但它没有回答问题。 Python 和 C++ 定义的整数除法和模数与您所说的一致,但一种使用取整除法,另一种使用舍入除法,因此它们不会表现出相同的行为。
      • 有不止一种方法可以做到这一点。这个问题也是关于x % y 的值。可以要求,对于正 y,0 <= x % y < y,这是您可能想到的,也是我更喜欢的。但是,正如正确答案所示,对于正 y,C++11 实际上具有 0 <= | x % y | < y 并且 x 的符号等于 x % y 的符号(如果非零),
      猜你喜欢
      • 2013-04-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多