这是一个非常基本的问题。请别介意,但我得问个问题。两个整数相加
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)
是正确的吗?
那么如何实现c= a+b对于a= 2147483648和b= 2147483648, c应该是整数还是双整数?
当您执行任何类型的输入操作时,您必须始终包含错误检查!对于流操作符,可以像这样:
int n;
if (!(std::cin >> n)) { std::cerr << "Error!n"; std::exit(-1); }
// ... rest of program
如果这样做,您将看到初始的a
提取已经失败,因此之后读取的任何值都没有很好地定义。
提取失败的原因是文字标记"2147483648
"在您的平台上不表示类型为int
的值(它太大了),与"1z
"或"Hello
"没有什么不同。
编程的真正危险在于默默假定输入操作成功,而实际上通常并不成功。尽早失败,越吵越好。
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,但是是无符号的。
c = 2 ^ 31 + 2 ^ 31日
c = 2 ^ (31 + 31)
是正确的吗?
不,但你是对的,结果需要超过31位。在这种情况下,结果占用32位(而2^(31+31)将占用62位)。你把乘法和加法搞混了:2^31 * 2^31 = 2^(31+31)。
无论如何,你要处理的基本问题叫做溢出。有几个选择。您可以检测它并将其作为错误报告,检测它并以获得答案的方式重新计算,或者只是使用允许您正确执行计算的数据类型,无论输入类型是什么。
在C和c++中,有符号溢出在技术上是未定义的行为,所以检测包括弄清楚哪些输入值会导致它(因为如果你执行操作,然后查看结果,看看是否发生溢出,你可能已经触发了未定义的行为,你不能指望任何事情)。这里有一个问题,详细介绍了这个问题:检测C/c++中的有符号溢出
或者,您可以使用不会为任何输入值溢出的数据类型来执行操作。例如,如果输入是int
s,那么任何一对int
s的正确结果都可以存储在更宽的类型中,例如(取决于您的实现)long
或long long
。
int a, b;
...
long c = (long)a + (long)b;
如果int
是32位,那么它可以保存[-2^ 31,2 ^31-1]范围内的任何值。所以最小的值是-2^31 + -2^31
,也就是-2^32
。可得的最大值是2^31 - 1 + 2^31 - 1
,也就是2^32 - 2
。所以你需要一个类型来保存这些值以及它们之间的所有值。一个额外的位足以容纳任何可能的加法结果(一个33位的整数可以容纳[-2^32,2^32-1]中的任何整数)。
或者,由于double
可能可以表示您需要的每个整数(64位IEEE 754浮点数据类型可以精确地表示最多53位的整数),您也可以使用双精度进行加法(尽管添加double
s可能比添加long
s慢)。
如果你有一个提供任意精度算术的库,你也可以使用它。