我将参考下面的代码来解释我的问题。
typedef long long int ll;
void func(){
ll lli_a = 603828039791327040;
ll lli_b = 121645100408832000;
double d_b = (double)lli_b;
cout << "a " << lli_b - d_b << endl; \\0
cout << "b " << (lli_a - 4*lli_b) - (lli_a - 4*d_b) << endl; \\64
cout << "c " << (lli_a - 4*lli_b) - (lli_a - (ll)4*d_b) << endl; \\64
cout << "d " << (lli_a - 4*lli_b) - (lli_a - 4*(ll)d_b) << endl; \\0
cout << "e " << 4*(ll)d_b - 4*d_b << endl; \\0
cout << "f " << 4*(ll)d_b - (ll)4*d_b << endl; \\0
}我无法理解为什么语句b和c计算为64,而d计算为0,这恰好是正确的答案。
E和f的计算值都为0,因此,由于从lli_a中减去,所以差别就出现了。我不认为存在任何溢出问题,因为每个术语的单个值都是正确的。
发布于 2022-01-13 07:09:26
一些代码可以让您通过它,底线不混入双倍与ints隐式
#include <cassert>
#include <iostream>
#include <type_traits>
// typedef long long int ll; NO , use using and never use aliasing to safe a bit of typing. Aliases are there to introduce meaning not shortcuts
//using namespace std; // also NO
int main()
{
long long int lli_a = 603828039791327040;
long long int lli_b = 121645100408832000;
//double d_b = (double)lli_b; // No this is C++ don't use 'C' style casts
double d_b = static_cast<double>(lli_b);
assert(static_cast<long long int>(d_b) == lli_b); // you are in luck the double can represent your value exectly, NOT guaranteed
std::cout << "a " << lli_b - d_b << "\n"; // endl; \\0 don't use endl unless you have a good reason to flush
long long int lli_b4 = 4 * lli_b;
// use auto to show you this expression evaluates to a double!
auto lli_d_b4 = (lli_a - static_cast<long long int>(4) * d_b); // d_b is double!!! what do you want to do here? Use it as a long long int then cast it first
static_assert(std::is_same_v<double, decltype(lli_d_b4)>);
auto result_c = lli_b4 - lli_d_b4;
// result c is still a double!
static_assert(std::is_same_v<double, decltype(result_c)>);
std::cout << "c " << result_c << "\n";
// long story short don't mix types implicitly and use "C++" style cast explicitly to get the results you want
/*
cout << "b " << (lli_a - 4 * lli_b) - (lli_a - 4 * d_b) << endl; \\64
cout << "c " << (lli_a - 4 * lli_b) - (lli_a - (ll)4 * d_b) << endl; \\64
cout << "d " << (lli_a - 4 * lli_b) - (lli_a - 4 * (ll)d_b) << endl; \\0
cout << "e " << 4 * (ll)d_b - 4 * d_b << endl; \\0
cout << "f " << 4 * (ll)d_b - (ll)4 * d_b << endl; \\0
*/
return 0;
}发布于 2022-01-13 06:47:50
double是浮点类型。浮点类型的精度有限。它们不能代表所有的数字,甚至不代表所有的有理数。简单地(在您的系统上) 603828039791327040是一个不能用double数据类型表示的数字。可表示的最接近的值恰好与精确值相距64。
您可以(很可能)通过使用long double (通常)表示long long的所有值来获得预期的结果--或者首先可以避免使用浮点数。
https://stackoverflow.com/questions/70692366
复制相似问题