我正在编写一个小型的最小公倍数算法并遇到了一些我不太了解的问题。这是代码的第一部分和最后一部分:
long a = 14159572;
long b = 63967072;
int rest = 4;
long long ans;
.
. // Some other code here that is not very interesting.
.
else
{
//This appears correct, prints out correct answer.
ans = b/rest;
std::cout << a*ans;
}
但如果我改变了最后的&#34;否则&#34;对此,它给出了一个小得多且不正确的答案:
else
{
std::cout << a*(b/rest);
}
任何人都知道这是为什么?我不认为这是一个溢出因为它没有出现错误的负数,而是一个比实际答案小得多的整数(大约6 * 10 ^ 8)(大约2.2 * 10 ^ 14)。据我了解,它应该计算&#34; b / rest&#34;首先在两种情况下,所以答案应该不同?
答案 0 :(得分:2)
差异不是运营顺序,而是数据类型:
ans = b/rest; // b/rest is long which upscaled to long long
std::cout << a*ans; // a converted to long long and result is long long
VS
std::cout << a*(b/rest); // a*(b/rest) all calculations in long
因此,如果您将第二个变体更改为:
std::cout << a*static_cast<long long>(b/rest);
你应该看到相同的结果。
更新为什么你的演员不起作用,请注意区别:
long a,b;
// divide `long` by `long` and upscale result to `long long`
std::cout << static_cast<long long>( a / b );
// upscale both arguments to `long long` and divide `long long` by `long long`
std::cout << a / static_cast<long long>( b );
答案 1 :(得分:2)
你仍然遇到溢出。仅仅因为你没有观察到负数并不意味着没有溢出。
在具体情况下,long
几乎肯定是一个32位整数,而long long
可能是一个64位整数。
由于32位有符号整数的最大值大约为20亿,因此14159572 * (63967072 / 4)
绝对超出范围。
确保使用long long
号码执行计算,或者重新考虑您的代码以避免首先出现溢出。
答案 2 :(得分:0)
编译器假设数学方程式的每个操作数的数据类型,并根据这些假定的数据类型进行乘法和除法(参见&#34;整数除法&#34;)。这也适用于计算的中间体。这也适用于传递给流的结果,因为您不传递显式定义类型的变量。