这是一个非常基本的问题。请不要介意,但我需要问这个问题。添加两个整数
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应该是整数还是双整数?
答案 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慢。
如果您有一个提供任意精度算术的库,您也可以使用它。