Qt qreal计算错误

时间:2017-04-06 11:02:23

标签: c++ qt

我想使用QGraphicsItem修改QSpinBox的不透明度。 QSpinBox为我提供了值 57 ,我用它来设置项目的不透明度。 然后我从项目中获得更改的不透明度,并希望填充QSpinBox。但设置框的值会导致错误。

qDebug() << (int)(qreal)(0.57 * 100.0);

输出 56

这是一个已知的错误吗? 有解决方法吗?

3 个答案:

答案 0 :(得分:6)

原因

由于计算不准确,不要依赖浮点数的精度。您可以阅读有关此问题的更多信息herehere

示范

如果使用qSetRealNumberPrecision为输出设置更高的精度,您将看到问题的实际根源 - 0.57 * 100.0的结果不准确 57 但是类似 56.999999999999992895

qDebug() << qSetRealNumberPrecision(20) << 0.57 * 100.0;

解决方案

因此,最好将round您的数字简化为最接近的整数而不是转换为int ,这只是省略了分数

qDebug() << qRound(0.57 * 100.0);

答案 1 :(得分:3)

适合尾数的整数在浮点中具有精确表示,因此static_cast<qreal>(100.0) == 100始终保持并表示为100*2^0

只要分子适合尾数,具有2^-n形式的分母的理性在浮点中也具有精确的表示,例如,只要您的编译器没有使用脑死亡的十进制到浮点转换函数,static_cast<qreal>(0.25*4) == 1就会成立。当大多数编译器解析代码时,它们将0.254转换为浮点表示,然后执行乘法以获取常量表达式的值。

但是static_cast<qreal>(0.57)没有m*2^-n的表示形式,只有足够小的整数m,n,并且必然表示不完整。它可以表示为小于或大于0.57。因此,当您将其乘以100时,它可能略小于57 - 在您的情况下。

最简单的解决方法是避免往返:将不透明度作为整数存储在各处,并且在更改值时仅从整数转换为浮点。换句话说,只使用setOpacity()方法,而不使用opacity()方法。使用项目的数据属性存储整数值不透明度:

void setOpacity(QGraphicsItem * item, int opacity) {
  item->setData(kOpacity, opacity);
  item->setOpacity(opacity / 100.0);
}

void getOpacity(QGraphicsItem * item) {
  auto data = item->data(kOpacity);
  if (! data.isNull())
    return data.toInt();
  int opacity = round(item->opacity() * 100.0);
  setOpacity(item, opacity);
  return opacity;
}

答案 2 :(得分:-1)

我找到了一个临时解决方案,但我对此并不满意。

qDebug() << "qreal" << (int)(qreal)(0.57 * 100.0);
qDebug() << "double" << (int)(double)(0.57 * 100.0);
qDebug() << "float" << (int)(float)(0.57 * 100.0);

输出: qreal 56, 双56, 漂浮57