当乘以10的倍数时失去双精度

时间:2013-08-21 15:14:15

标签: c++

所以我有以下代码

int main(){

double d;
cin>>d;

while(d!=0.00)
{
    cout<<d<<endl;
    double m = 100*d;
    int n = m;
    cout<<n<<endl;
    cin>>d;
}

return 0;}

当我为d输入输入20.40时,n的值为2039而不是2040。 我尝试用int n = m替换int n = (int) m,但结果是一样的。 有没有什么办法解决这一问题。提前谢谢。

5 个答案:

答案 0 :(得分:3)

您的代码会截断m,但您需要舍入。包括cmath并使用int n = round(m)

答案 1 :(得分:2)

通常,十进制值不能使用像double这样的二进制浮点精确表示。因此,值20.40被表示为近似值,其可用于恢复原始值(20.4;精度不能保留),例如,在格式化值时。使用这些近似值进行计算通常会放大误差。

正如其中一篇评论中已经提到的,相关参考文献是paper“每个计算机科学家应该知道的关于浮点算术的内容”。解决问题的一种可能方法是使用十进制浮点数,但这不是{+ 3}} C ++标准的一部分。

答案 2 :(得分:1)

单和双预设浮点数的存储方式与整数的存储方式不同,因此整数(例如5,10)实际上可能看起来像长小数(例如4.9999001,10.00000000001)。当你转换为int时,它只会截断整数。因此,如果该号码目前被表示为4.999999999,则将其投放到int会给您4std::round会在大多数情况下为您提供更好的结果(如果数字是4.6而您只想要整数部分,则圆形将无法正常工作)。那么更大的问题是:你希望通过将double投射到int来实现什么目标?

通常,在处理浮点数时,您需要使用一些 epsilon 值,这是您的最小有效数字。所以如果你想比较4.9999999到5,你会做(伪代码):if abs(5 - 4.9999999) < epsilon, return 5

示例

int main()
{
    double d;
    std::cin >> d;

    while (std::fabs(d - 0.0) > DBL_EPSILON)
    {
        std::cout << d << std::endl;
        double m = 100 * d;
        int n = static_cast<int>(m);
        if (std::fabs(static_cast<double>(n) - m) > DBL_EPSILON)
        {
            n++;
        }
        std::cout << n << std::endl;
        std::cin >> d;
    }

    return 0;
}

答案 3 :(得分:0)

将double转换为int截断值,因此20.40可能是20.399999 * 100是2039.99,因为double不是基数10.您可以使用不会截断但最接近int的round()函数。

int n = round(m);

答案 4 :(得分:0)

浮点数不能精确表示所有十进制数,有时会使用近似值。在您的示例中,最接近的确切数字是20.39999999999999857891452847979962825775146484375。有关查看确切值的快速方法,请参阅IEEE-754 Analysis

你可以使用舍入,但可能你真的在寻找截断的前两位数字。只需添加一个非常小的值,例如在乘以之前或之后0.0000000001。