in reply to Re^5: Normalizing a range of numbers to a percentage
in thread Normalizing a range of numbers to a percentage

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;

Replies are listed 'Best First'.
Re^7: Normalizing a range of numbers to a percentage
by swl (Prior) on Mar 08, 2019 at 07:44 UTC

    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.

      "shift, scale, rescale, and re-shift"

      Excellent !!