c++ - 如何克服 double 不准确?

标签 c++ precision floating-point-precision double-precision

我的函数是去掉两个 double 的小数部分,同时保留它们的比例:

void enlarge(double &a, double &b)
{
    while (a != trunc(a) || b != trunc(b))
    {
        a *= 10;
        b *= 10;
        //output added for debugging
        cout << "a = " << a << ", b = " << b << endl;
        cout << "trunc(a) = " << trunc(a) << ", trunc(b) = " << trunc(b) << endl;
        cout << "a == trunc(a): " << to_string(a == trunc(a)) << ", b == trunc(b): " << to_string(b == trunc(b)) << endl;
        //to see output step by step
        string asd;
        cin >> asd;
    }
}

停止正常工作时的输出:

a = 0.876, b = 99.9
trunc(a) = 0, trunc(b) = 99
a == trunc(a): 0, b == trunc(b): 0
a
a = 8.76, b = 999
trunc(a) = 8, trunc(b) = 999
a == trunc(a): 0, b == trunc(b): 1
a
a = 87.6, b = 9990
trunc(a) = 87, trunc(b) = 9990
a == trunc(a): 0, b == trunc(b): 1
a
a = 876, b = 99900
trunc(a) = 876, trunc(b) = 99900    //This is where it stops working
a == trunc(a): 0, b == trunc(b): 1  //Notice how 876 != 876
a
a = 8760, b = 999000
trunc(a) = 8760, trunc(b) = 999000
a == trunc(a): 0, b == trunc(b): 1

遇到这种情况我该怎么办?

最佳答案

问题是原始数字不是完全 .876,尽管差别不大。所以你可能需要多次乘以 10 才能得到一个整数。

另外,请注意,如果数字略小于 .876,则数字的 1000 倍将略小于 876.0,并且 trunc(875.99999999...) 是 875,而不是 876。

您可能会考虑一些阈值,其中数字“足够接近”整数。例如,不使用 a==trunc(a),您可以使用测试

abs(a - round(a)) < 1e-6

最后,如果你想要精确,你可以在每一步乘以 2,而不是乘以 10。每次乘以 10 都会失去一点精度,因为 10 不是 2 的幂。乘以 2将在最多 52 次乘法后产生一个整数。

关于c++ - 如何克服 double 不准确?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29130045/

相关文章:

c++ - 如何有效地对__m256i vector 的字节重新排序(将int32_t转换为uint8_t)?

c++ - 具有 VARIANT 返回类型的模板实例化

floating-point - go中的浮点运算

c - 使用浮点变量作为循环计数器及其在非 "=="条件下的小数递增/递减有任何风险吗?

c++ - 如何将 C++ 编译的 dll 函数挂接到 sql 数据库?

python - Fortran 和 Python 中的精度和多项式评估

c++ - 如何在C++中将字符串转换为具有指定精度的 double

c++ - 为什么 "possible lack of precision"不是编译器错误?

c# - 获取下一个最小的 Double 数

c++ - MiXiM 包含错误