C ++中的整数除法没有按预期工作

时间:2014-01-14 00:02:42

标签: c++

我是新来的,所以非常抱歉,如果这是基本的,但我在这里缺少什么?这只是一个虚拟代码:

#include <iostream>
using namespace std;

int main() {
    unsigned int a, b, c;
    int d;
    a = 10E06;
    b = 25E06;
    c = 4096;
    d = (a - b)/c;
    std::cout << d << std::endl;
    return 0;
}

cout正在打印1044913而不是-3662。如果我把a和b转换成长期问题就解决了。是否存在溢出问题?

5 个答案:

答案 0 :(得分:4)

那是因为(a-b)本身是无符号的:

#include <iostream>
using namespace std;

int main() {
    unsigned int a, b, c;
    int d;
    a = 10E06;
    b = 25E06;
    c = 4096;
    d = (a - b)/c;
    std::cout << (a-b) << std::endl; // 4279967296
    std::cout << d << std::endl; // 1044913 
    return 0;
}

unsigned转换为int时会发生d,而不是之前。

所以(a-b)/c必须是无符号的,因为a,b,c是。

答案 1 :(得分:3)

无符号数之间的运算产生无符号数。这取决于你确保操作有意义,或防止相反。

如果您有unsigned int a = 2, b = 3;,您认为a-b的价值是什么?

答案 2 :(得分:2)

由于b和c都被声明为无符号,因此计算(a-b)/ c的输出将是无符号的。由于您提供的值的计算无法使用无符号类型正确表示,因此事情变得有点混乱。然后将无符号值分配给d,即使这是有符号的,该值也已经是乱码。

我还要注意,符号10E06表示一个浮点数,然后隐式地转换为unsigned int。根据提供的特定浮点值,这可能会或可能不会按预期进行投射。

答案 3 :(得分:1)

您希望您的结果带有标志。因此,您应该将变量声明为signed int或int。这将产生预期的结果。如果你将a和b转换为long,a-b将会很长,因此需要一个符号。以下是一个解决方案。

int main() {
    int a, b, c;
    int d;
    a = 10E06;
    b = 25E06;
    c = 4096;
    d = (a - b)/c;
    std::cout << d << std::endl;
    return 0;
}

如果你也想要有理数,你应该使用双打或浮点数(尽管它不会为这个特殊情况给出不同的结果)。

int main() {
    double a, b, c;
    double d;
    a = 10E06;
    b = 25E06;
    c = 4096;
    d = (a - b)/c;
    std::cout << d << std::endl;
    return 0;
}

答案 4 :(得分:1)

由于C ++(以及许多其他基于C语言)处理运算符的方式,当无符号数放入表达式时,该表达式返回无符号值,而不是保持在一个神秘的类型间状态,可能是预期

步骤一步:

  • (a - b)从10E06中减去25E06,它通常会返回-15E06,是无符号的,所以它被包裹在一大堆垃圾中。
  • 然后将此垃圾除以c,两个输入都是无符号的,因此输出也是无符号的。
  • 最后,这是填入签名的int,保留在1044913。

“unsigned int”是一个类似float和bool的类型,即使它需要两个关键字。如果您希望它变成用于该计算的signed int,则必须确保a,b和c都已签名(删除unsigned关键字),或者在将它们放入表达式时将其强制转换,如下所示: d = ((signed)a - (signed)b) / (signed)c;