【问题标题】:C++ appears to violate properties of additionC++ 似乎违反了加法的性质
【发布时间】:2014-09-18 20:30:52
【问题描述】:

在做课堂作业时,我遇到了这个问题(注意循环的条件)

// This one works.
for (int k = 0; k + negwords[j].length() < comments[i].length(); k++) {
    if (comments[i].substr(k, negwords[j].length()) == negwords[j]) {
        negativeScore++;
    }
}
//*/

/*/ This one doesn't: It fails with an out-of-bounds index.
for (int k = 0; k < comments[i].length() - negwords[j].length(); k++) {
    if (comments[i].substr(k, negwords[j].length()) == negwords[j]) {
        negativeScore++;
    }
}
//*/

为什么第一个有效,第二个无效?是关于操作顺序、bool 强制转换为 int、运算符关联性还是 OBOE?

【问题讨论】:

  • length() 是否返回无符号类型?
  • 不应该是 k + cmets[i].length()
  • @cyan: 不,如果你从第一个循环条件的两边减去negwords[i].length(),你会得到第二个。
  • 请说明negwords和cmets的定义。
  • 通过正确编译(例如,对于 gcc,您应该至少使用 -Wall 编译(!)),失败的代码应该会警告您有关有符号和无符号整数之间的比较

标签: c++


【解决方案1】:

如果negwords[j].length()comments[i].length() 返回至少与unsigned int 一样大的无符号整数类型,则k 将被提升为相同的无符号类型,并且将适用模加法规则

例如,这意味着1 &lt; 2 - 3 为真,因为2 - 3 在模运算中环绕,成为一个非常大的数字。

如果您有兴趣,此行为在标准的第 3.9.1 节中指定,其中包括规则:

无符号整数应遵循算术模 2 定律n 其中 n 是该特定大小的值表示中的位数整数。

以及有关含义的脚注:

48 这意味着无符号算术不会溢出,因为无法由生成的无符号整数类型表示的结果以比可以表示的最大值大一的数字为模减少得到的无符号整数类型。


数学家将这种类型的算术称为伽罗瓦域的代数。在 C++ 中,它用于无符号整数类型。其他类型不使用模算术,但它们也不使用普通的小学算术(正式地,实数代数),因为普通算术需要一组密集的不可数数,并且有限大小的计算机无法表示无限集的成员。

感谢 Oliver 指出我的错误。 GF(2)^n 确实控制了按位运算和在计算机软件中完成的一大堆其他常见计算,例如 CRC。但它没有描述超过 1 位的无符号算术,因为伽罗瓦域上的多项式不“进位”。

【讨论】:

  • @Cyber​​:不,下溢是DBL_MIN / 2.0 * 2.0 为零。这是环绕式。
猜你喜欢
  • 1970-01-01
  • 2014-08-09
  • 2015-08-07
  • 1970-01-01
  • 1970-01-01
  • 2016-11-11
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多