操作顺序不正确? (C++)
Order of operations not correct? (C++)
我在写一个小的最小公倍数算法,遇到了一些我不明白的地方。这是代码的第一部分和最后一部分:
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;
}
但是如果我将最后一个 "else" 更改为这个,它给出的答案会更小且不正确:
else
{
std::cout << a*(b/rest);
}
有人知道这是为什么吗?我不认为这是一个溢出,因为它不是错误的负数,而是一个比实际答案(大约 2.2*10^14)小得多的整数(大约 6*10^8)。据我了解,在这两种情况下,它都应该首先计算 "b/rest",所以答案应该没有什么不同?
区别不在于操作顺序,而在于数据类型:
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
对比:
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 );
您仍然遇到溢出问题。仅仅因为您没有观察到负数并不意味着没有溢出。
在您的具体情况下,long
几乎肯定是一个 32 位整数,而 long long
可能是一个 64 位整数。
由于 32 位有符号整数的最大值约为 20 亿,14159572 * (63967072 / 4)
肯定超出了范围。
确保您使用 long long
数字执行计算,否则请重新考虑您的代码以避免首先出现溢出。
编译器假定数学方程式的每个操作数的数据类型,并根据这些假定的数据类型进行乘法和除法运算(请参阅 "integer division")。这也适用于计算的中间过程。这也适用于传递给流的结果,因为您没有传递明确定义类型的变量。
我在写一个小的最小公倍数算法,遇到了一些我不明白的地方。这是代码的第一部分和最后一部分:
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;
}
但是如果我将最后一个 "else" 更改为这个,它给出的答案会更小且不正确:
else
{
std::cout << a*(b/rest);
}
有人知道这是为什么吗?我不认为这是一个溢出,因为它不是错误的负数,而是一个比实际答案(大约 2.2*10^14)小得多的整数(大约 6*10^8)。据我了解,在这两种情况下,它都应该首先计算 "b/rest",所以答案应该没有什么不同?
区别不在于操作顺序,而在于数据类型:
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
对比:
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 );
您仍然遇到溢出问题。仅仅因为您没有观察到负数并不意味着没有溢出。
在您的具体情况下,long
几乎肯定是一个 32 位整数,而 long long
可能是一个 64 位整数。
由于 32 位有符号整数的最大值约为 20 亿,14159572 * (63967072 / 4)
肯定超出了范围。
确保您使用 long long
数字执行计算,否则请重新考虑您的代码以避免首先出现溢出。
编译器假定数学方程式的每个操作数的数据类型,并根据这些假定的数据类型进行乘法和除法运算(请参阅 "integer division")。这也适用于计算的中间过程。这也适用于传递给流的结果,因为您没有传递明确定义类型的变量。