我想使用QGraphicsItem
修改QSpinBox
的不透明度。
QSpinBox
为我提供了值 57 ,我用它来设置项目的不透明度。
然后我从项目中获得更改的不透明度,并希望填充QSpinBox
。但设置框的值会导致错误。
qDebug() << (int)(qreal)(0.57 * 100.0);
输出 56
这是一个已知的错误吗? 有解决方法吗?
答案 0 :(得分:6)
由于计算不准确,不要依赖浮点数的精度。您可以阅读有关此问题的更多信息here或here。
如果使用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.25
和4
转换为浮点表示,然后执行乘法以获取常量表达式的值。
但是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