在发布版本中将两个双打分开的结果错误

时间:2019-04-17 09:10:29

标签: c++ double mingw32 divide

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

我试图将类型从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可以 minimumArmorDelta是int = 5

那为什么40/5不是8?

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

屏幕截图: Release Debug

3 个答案:

答案 0 :(得分:0)

我想,原因是armorPointsPerHalfTon / minimumArmorDelta在发行版中可能不是8,而实际上是7.99999999。然后,通过int-cast将该值更改为7。

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

由于在Release版本中进行了一些优化,因此Debug / Release产生不同的结果(按机器精度的顺序)也就不足为奇了。

编辑:如果它满足您的要求,您可以使用std::round将双精度舍入到最接近的整数,而不是舍入小数。

答案 1 :(得分:0)

@朱利安 我也怀疑,但是如何克服这个障碍呢?将尝试将步骤更改为两倍,然后再次转换为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 s会冲洗掉某些东西,这就是为什么现在步骤计算正确的原因。不过,字符串的值不正确为“ 7”。

答案 2 :(得分:0)

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

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

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