C ++中的基本整数解释

时间:2011-12-29 12:03:02

标签: c++

这是一个非常基本的问题。请不要介意,但我需要问这个问题。添加两个整数

int main()
{
     cout<<"Enter a string: ";
     int a,b,c;
     cout<<"Enter a";
     cin>>a;
     cout<<"\nEnter b";
     cin>>b;
     cout<<a<<"\n"<<b<<"\n";
     c= a + b;
     cout <<"\n"<<c ;
     return 0;
}

如果我给a = 2147483648那么 b自动获取值4046724.请注意,不会提示cin 结果c是7433860

如果int为2 ^ 32且第一位为MSB则为2 ^ 31

c = 2 ^ 31 + 2 ^ 31

C = 2 ^(31 + 31)

这是正确的吗?

那么如何为a = 2147483648和b = 2147483648实现c = a + b并且c应该是整数还是双整数?

3 个答案:

答案 0 :(得分:2)

执行任何类型的输入操作时,必须始终包含错误检查!对于流操作符,这可能如下所示:

int n;
if (!(std::cin  >> n)) { std::cerr << "Error!\n"; std::exit(-1); }
// ... rest of program

如果你这样做,你会发现a的初始提取已经失败,因此之后读取的任何值都没有明确定义。

提取失败的原因是文字标记“2147483648”不代表您平台上类型int的值(它太大),与“{ {1}}“或”1z“。

编程中的真正危险是静默地假设输入操作成功但通常不成功。尽可能早地和吵闹地失败。

答案 1 :(得分:1)

int类型已签名,因此它的最大值为2 ^ 31-1 = 2147483648 - 1 = 2147483647 即使您使用无符号整数,它的最大值也是2 ^ 32 -1 = a + b - 1表示您给出的a和b的值。 对于你正在做的算术,你应该更好地使用“long long”,其最大值为2 ^ 63-1并且是有符号的或“unsigned long long”,其最大值为2 ^ 64-1但是未签名。

答案 2 :(得分:0)

  

c = 2 ^ 31 + 2 ^ 31

     

C = 2 ^(31 + 31)

     

这是正确的吗?

不,但你说得对,结果需要超过31位。在这种情况下,结果需要32位(而2 ^(31 + 31)将占用62位)。你将乘法与加法混淆:2 ^ 31 * 2 ^ 31 = 2 ^(31 + 31)。

无论如何,你要求处理的基本问题叫做溢出。有几个选择。您可以检测它并将其作为错误报告,检测它并以获得答案的方式重新计算,或者只使用允许您正确计算的数据类型,无论输入类型是什么。

C和C ++中的签名溢出在技术上是未定义的行为,因此检测包括确定将导致它的输入值(因为如果您执行操作然后查看结果以查看是否发生溢出,则可能已触发未定义的行为,你不能指望任何事情)。以下是有关此问题的详细问题:Detecting signed overflow in C/C++

或者,您可以使用不会因任何输入值溢出的数据类型执行操作。例如,如果输入为int s,那么任何int对的正确结果都可以存储在更宽的类型中,例如(取决于您的实现)long或{{ 1}}。

long long

如果int a, b; ... long c = (long)a + (long)b; 是32位,那么它可以保持范围[-2 ^ 31,2 ^ 31-1]中的任何值。因此,可获得的最小值为int,即-2^31 + -2^31。可获得的最大值为-2^32,即2^31 - 1 + 2^31 - 1。因此,您需要一种能够保存这些值以及介于两者之间的每个值的类型。一个额外的位足以保存任何可能的加法结果(33位整数将保存[-2 ^ 32,2 ^ 32-1]中的任何整数)。

或者,由于2^32 - 2可能代表您需要的每个整数(64位IEEE 754浮点数据类型可以精确表示高达53位的整数),您也可以使用双精度进行加法(尽管添加double可能比添加double s慢。

如果您有一个提供任意精度算术的库,您也可以使用它。