Integers that fit in the mantissa have exact representation in floating point, thus static_cast<qreal>(100.0) == 100
always holds and is represented as 100*2^0
.
Rationals with denominators of the form 2^-n
also have exact representation in floating point as long as the numerator fits in the mantissa, thus e.g. static_cast<qreal>(0.25*4) == 1
holds as long as your compiler doesn't use a brain-dead decimal-to-floating-point conversion function. When most compilers parse the code, they convert both 0.25
and 4
to a floating point representation, and then perform the multiplication to obtain the value of the constant expression.
But static_cast<qreal>(0.57)
has no representation as m*2^-n
, with sufficiently small integer m,n
, and is necessarily represented inexactly. It can be represented as a bit less or more than 0.57
. Thus when you multiply it by 100
, it can be slightly less than 57
- in your case.
The simplest fix is to avoid the roundtrip: store the opacity everywhere as an integer, and only convert from integer to floating point when changing the value. In other words, only ever use the setOpacity()
method, and never use the opacity()
method. Store the integer-valued opacity using the item's data attribute:
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;
}