由于C++中双精度类型的准确性而导致的错误



我写了一个类来为我计算金额。下面是代码简介。

class RMB
{
private:
    int yuan;
    int jiao;
    int fen;
    bool mark;
public:
RMB(int yu, int ji, int fe, bool mar = true)
    {
        yuan = yu;
        jiao = ji;
        fen = fe;
        mark = mar;
    }
    RMB(double money)
    {
        int money1 = int(money * 100);
        yuan = money1 / 100;
        fen = money1 % 10;
        jiao = (money1 - yuan * 100 - fen)/10;
        if (money < 0) mark = 0;
        else mark = 1;
    }
    operator double()
    {
        double money = yuan + double(jiao) / 10 + double(fen) / 100;
        if (mark == false) return -money;
        return money;
    }
};
int main()
{
    RMB a(1,2,3);RMB b(2,3,4);
cout << "a + c = " << RMB(a + c) << endl;//assume I have override "<<" and ">>"
cout << "a - b = " << RMB(a - b) << endl;
}

但是当我测试我的代码时,它发生了:

a + c = 2 yuan 4 jiao 5 fen
a - b = -1 yuan -1 jiao 0 fen

我在VS2015中对其进行了测试,我已经对其进行了调试,double(a-b)的确切值是-1.199999998。那么我该如何修复此错误以及我该如何避免此类错误呢?

国家英里最简单的方法是使用整数类型来表示货币价值并以美分为单位。对精确的十进制值使用二进制浮点类型永远不会有好结果。

如果您的编译器具有它们,请使用 std::uint64_t 作为类型,或者如果您需要负量的概念,请使用std::int64_t。这对于以津巴布韦元表示的世界GDP来说已经绰绰有余了。您甚至可以将其包装在class中以备将来验证。

C++故意不提供"开箱即用"的十进制类型。

RMB(double money)
{
    int money1 = int(money * 100);

如果钱是负数,钱1也是!

    yuan = money1 / 100;
    fen = money1 % 10;
    jiao = (money1 - yuan * 100 - fen)/10;

您的会员也是如此!

    if (money < 0)
        mark = 0;
    else
        mark = 1;

并且您另外存储标志(用于operator double(:

return mark ? money : -money;

假设你应该让你的成员成为积极的(那时我更喜欢未签名的成员(:

RMB(double money)
    : mark(money >= 0)
{
    unsigned int money1 = (int)((mark ? money : -money) * 100);
    // ...
}

我建议这样阅读:https://randomascii.wordpress.com/2012/02/25/comparing-floating-point-numbers-2012-edition/

为了更深入地处理这个主题,我建议:"每个计算机科学家都应该知道的关于浮点运算的知识"

最新更新