my $x = (($tap - $min) * ($new_max - $new_min) / ($max - $min)) + $new
+_min;
The offset on the new range has to be outside the multiply.
| [reply] [d/l] |
stevieb: I don't know how rusty your algebra is, but it's always good to go back to first principles: what you're doing is a liner transformation from an input number to an output number. So let's derive it using everybody's favorite line, y = mx + b. The y are your output points (y0 = $new_min and y1 = $new_max), the x are you input points (x0 = $min and x1 = $max). Then let's calculate a y from a given x (where x = $tap). (We'll ignore the fact that you called the output $x, just to confuse us, until the very end.)
#I# y0 = m*x0 + b
#II# y1 = m*x1 + b
Want to eliminate b, so we're down to one unknown:
#III# (y1-y0) = m*(x1-x0) + (b-b) #II#-#I#
#IV# (y1-y0) = m*(x1-x0) ## simplify
#V# m = (y1-y0)/(x1-x0) ## solve for m
Now we need to solve for b
#VI# y0 = (y1-y0)/(x1-x0)*x0 + b #V# into #I#
#VII# b = y0 - x0*(y1-y0)/(x1-x0) ## solve for b
Plug into the generic equation
#VIII# y = m*x + b ## generic
#IX# y = (y1-y0)/(x1-x0)*x + y0 - x0*(y1-y0)/(x1-x0) #V# and #VII# into #VIII#
#X# y = ( (y1-y0)*x - (y1-y0)*x0 )/(x1-x0) + y0 ## bring most over common denominator
#XI# y = ( y1*(x-x0) - y0*(x-x0) )/(x1-x0) + y0 ## group the y1's and the x1's
#XII# y = ( (y1-y0)*(x-x0) )/(x1-x0) + y0 ## combine the multipliers of (x-x0)
#XIII# y = (x-x0)*(y1-y0)/(x1-x0) + y0 ## reorder, remove extra parens
Convert to your notation
x0 => $min
x1 => $max
x => $tap
y0 => $new_min
y1 => $new_max
y => $x
y = (x-$min)*(y1-y0)/(x1-$min) + y0 ## substitute for x0 into #XIII#
y = (x-$min)*(y1-y0)/($max-$min) + y0 ## substitute for x1 into prev
y = ($tap-$min)*(y1-y0)/($max-$min) + y0 ## substitute for x into prev
y = ($tap-$min)*(y1-$new_min)/($max-$min) + $new_min ## substitute for y0 into prev
y = ($tap-$min)*($new_max-$new_min)/($max-$min) + $new_min ## substitute for y1 into prev
$x = ($tap-$min)*($new_max-$new_min)/($max-$min) + $new_min ## substitute for y into prev
And with my and the end semicolon, you now have the equation that typbalt89 gave: my $x = ($tap-$min)*($new_max-$new_min)/($max-$min) + $new_min;
| [reply] [d/l] [select] |
stevieb: pyrt's equation #XIII# is the key here.
I am probably labouring the point, but the process is to subtract the input min and divide by the input range to normalise into the interval 0,1, then rescale the result to the new range and shift it to the new minimum.
Another way of describing it is that it is four steps of shift, scale, rescale, and re-shift.
| [reply] [d/l] |