在发布版本中分割两个双精度的错误结果

问题描述 投票:-2回答:3

当我在发布模式下编译我的应用程序时,我得到40.0 / 5 = 7的错误除法结果。在调试编译中它是正确的,结果是8

我试图强制转换为double,从double到int,没有abs()等,但没有运气。我知道这必须与计算机上浮点数学的怪异有关,但我不知道到底是什么。我还通过代码下面的qDebugs()记录了控制台上的值 - 除了初始步骤外,一切看起来还不错。

//somewhere in code
   double tonnageToRecover = 0.5;//actually, its QDoubleSpinBox->value(), with 0.5 step set. Anyway, the value finally reduces to 0.5 every time
   double tonnagePerArmorPoint = 0.0125;//taken from .json
   int minimumArmorDelta = 5;//taken from .json
...
//palace where the calculations are preformed
    double armorPointsPerHalfTon = tonnageToRecover / tonnagePerArmorPoint;    
    int steps = abs(static_cast<int>(armorPointsPerHalfTon / minimumArmorDelta));
    qDebug() << "armorPointsPerHalfTon = " << armorPointsPerHalfTon;
    qDebug() << "tonnagePerArmorPoint = " << tonnagePerArmorPoint;
    qDebug() << "steps initial = " << steps;
    qDebug() << "minimumArmorDelta = " << minimumArmorDelta;

两个部分都是double类型,tonnageToRecover = 0.5,tonnagePerArmorPoint = 0.0125,结果是40,这是OK minimumArmorDelta是int = 5

那么为什么40/5不是8?

编译器 - MinGW 32 5.3.0,来自Qt 5.11 pack

截图:Release Debug

c++ double mingw32 divide
3个回答
0
投票

@Julian我也怀疑,但我怎样才能克服这个障碍?将尝试将步骤更改为double,然后再次转换为int。重置:仍然不起作用:/

我找到了一个解决方案,但我不知道为什么它现在有效。目前的代码:

    double armorPointsPerHalfTon = tonnageToRecover / tonnagePerArmorPoint;
//    int aPHT = (int)armorPointsPerHalfTon;
//    double minDelta = 5.0;//static_cast<double>(minimumArmorDelta);
    QString s(QString::number(abs(armorPointsPerHalfTon / minimumArmorDelta)));
    int steps = abs(armorPointsPerHalfTon / minimumArmorDelta);

#define myqDebug() qDebug() << fixed << qSetRealNumberPrecision(10)
    myqDebug() << "tonnageToRecover = " << tonnageToRecover;
    myqDebug() << "tonnagePerArmorPoint = " << tonnagePerArmorPoint;
    myqDebug() << "armorPointsPerHalfTon = " << armorPointsPerHalfTon;
    //myqDebug() << "aPHT = " << aPHT;//this was 39 in Release, 40 in Debug
    myqDebug() << "steps initial = " << steps;
    myqDebug() << "string version = " << s;
    myqDebug() << "minimumArmorDelta = " << minimumArmorDelta;// << ", minDelta = " << minDelta;
#undef myqDebug

我想那个QString的创建会刷新一些东西,这就是为什么现在计算步骤是正确的。但是,字符串的值不正确“7”。


0
投票

你的基本问题是你正在截断。

假设实数运算将给出准确的答案8.浮点运算将给出非常接近8的答案,但由于舍入误差可能在任一方向上都不同。如果浮点答案略大于8,则截断将其更改为8.如果它甚至略小于8,则截断将其更改为7。

我建议写一个关于如何避免截断的新问题,并讨论你为什么要这样做。


0
投票

我想,原因是armorPointsPerHalfTon / minimumArmorDelta可能不是8但实际上是7.99999999在Release版本中。然后,此值通过int-cast更改为7。

因此,如果Debug版本计算armorPointsPerHalfTon / minimumArmorDelta = 8.0000001,则结果为static_cast<int>(armorPointsPerHalfTon / minimumArmorDelta) = 8

调试/发布会产生不同的结果(按照机器精度的顺序)并不奇怪,因为发布版本中会出现一些优化。

编辑:如果它符合您的要求,您可以使用std::round将您的double舍入到最接近的整数,而不是截断小数。

© www.soinside.com 2019 - 2024. All rights reserved.