If I simply perform s = y / x is there any chance that floor(x * s) won't be equal to y due to floating point operations?
Yes, there is a chance it won't be equal. @Eric Postpischil offer a simple counter example: y = 1 and x = 49.
(For discussion, let us limit x,y > 0
.)
To find a scale factor s
for a given x,y
, that often works, we need to reverse y = floor(x * s)
mathematically. We need to account for the multiplication error (see ULP) and floor truncation.
# Pseudo code
e = ULP(x*s)
y < (x*s + 0.5*e) + 1
y >= (x*s - 0.5*e)
# Estimate e
est = ULP((float)y)
s_lower = ((float)y - 1 - 0.5*est)/(float)x
s_upper = ((float)y + 0.5*est)/(float)x
A candidate s
will lie s_lower < s <= s_upper
.
Perform the above with higher precision routines. Then I recommend to use the float closest to the mid-point of s_lower, s_upper
.
Alternatively, an initial stab at s
could use:
s_first_attempt = ((float)y - 0.5)/(float)x
AccessDenied
" – chux - Reinstate Monica Jun 28 '21 at 12:57