Author Topic: A simple approach to translate a value from its original range to another range  (Read 4185 times)

0 Members and 1 Guest are viewing this topic.

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Hi guys and gals

what do you think about the QB45 instuction PMAPhttp://www.qb64.org/wiki/PMAP? It is a useful function set to translate between physical screen cohordinates and WINDOW logical cohordinates...
but what do you think if it was possible to translate a value (cohordinate or scalar value) from a range to another with a simple function?
Here I post a simple approach to this issue comparing two methods...
Proportion vs Normalization
Code: QB64: [Select]
  1. DIM iValue AS INTEGER, iMin AS INTEGER, iMax AS INTEGER
  2. DIM iNewMin AS INTEGER, iNewMax AS INTEGER
  3. DIM dNewValue AS DOUBLE, dNewValue2 AS DOUBLE
  4.  
  5.  
  6. iMin = 1
  7. iMax = 10
  8. iNewMin = 10
  9. iNewMax = 100
  10. PRINT " StartValue    Proportion    Translation"
  11. FOR i = 2 TO 7 STEP 1
  12.     iValue = i
  13.     dNewValue = Proportion#
  14.     dNewValue2 = Normalize#
  15.     PRINT iValue, dNewValue, dNewValue2
  16.  
  17.  
  18.  
  19. END ' local end of the program
  20.  
  21. FUNCTION Proportion#
  22.     DIM Delta1 AS INTEGER, Delta2 AS INTEGER
  23.     SHARED iValue AS INTEGER, iMin AS INTEGER, iMax AS INTEGER
  24.     SHARED iNewMin AS INTEGER, iNewMax AS INTEGER
  25.     ' Delta1:Delta2 = iValue : iValue2
  26.     ' iValue2 = (Delta2 * ivalue) /Delta1
  27.     Delta1 = iMax - iMin
  28.     Delta2 = iNewMax - iNewMin
  29.     Proportion# = (iValue * Delta2) / Delta1
  30.  
  31. FUNCTION Normalize#
  32.     SHARED iValue AS INTEGER, iMin AS INTEGER, iMax AS INTEGER
  33.     SHARED iNewMin AS INTEGER, iNewMax AS INTEGER
  34.  
  35.     'valore normalizzato =  minimoscala+
  36.     '((osservazione-MIN(intervallo))/
  37.     '(MAX(intervallo)-MIN(intervallo))*
  38.     '(massimoscala-minimoscala)
  39.  
  40.     Normalize# = iNewMin + ((iValue - iMin) / (iMax - iMin) * (iNewMax - iNewMin))
  41.  
what method do you prefer?
Thanks to read
Programming isn't difficult, only it's  consuming time and coffee

Offline Richard Frost

  • Seasoned Forum Regular
  • Posts: 316
  • Needle nardle noo. - Peter Sellers
    • View Profile

Variables prefixed with an "i" are reserved for Apple products.

My translation method uses a hammer.  Yours is far better, since
it works to expand too.  Your 2nd SUB (Normalize#) is best, because
it's only one line.  Both your methods should test for zero, as
dividing by it makes a CPU very grumpy.

« Last Edit: October 16, 2020, 11:05:07 pm by Richard Frost »
It works better if you plug it in.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
@TempodiBasic

I thought Fellippe's map function covered things quite well.

reminder:
Code: QB64: [Select]
  1. FUNCTION map! (value!, minRange!, maxRange!, newMinRange!, newMaxRange!)
  2.     map! = ((value! - minRange!) / (maxRange! - minRange!)) * (newMaxRange! - newMinRange!) + newMinRange!
  3.  

Using WINDOW automatically does most of this.
« Last Edit: October 17, 2020, 11:37:36 am by bplus »

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
@bplus
I'm glad you know the map! function of pj library. 
you're right about all except that
   1. the map! function has been translated into QB64 by  Fellippe & Ashish
   2. it releases a single value
   3. my normalize# function has the same radix but it releases a double value
in this post my goal was to evaluate 2 mathematical methods... the Proportion vs the Normalization formulas...
I have used the double type of data to see if there was a significant difference between the two formulas because from my hobbyst point of view I don't know if the difference in calculations is significant or not...
Code: QB64: [Select]
  1. DIM iValue AS SINGLE, iMin AS SINGLE, iMax AS SINGLE
  2. DIM iNewMin AS SINGLE, iNewMax AS SINGLE
  3. DIM dNewValue AS DOUBLE, dNewValue2 AS DOUBLE
  4.  
  5.  
  6. iMin = 1
  7. iMax = 10
  8. iNewMin = 10
  9. iNewMax = 100
  10. PRINT " StartValue    Proportion    Translation"
  11. FOR i = 2 TO 7 STEP .7
  12.     iValue = i
  13.     dNewValue = Proportion#
  14.     dNewValue2 = Normalize#
  15.     PRINT iValue, dNewValue, dNewValue2
  16.  
  17.  
  18.  
  19. END ' local end of the program
  20.  
  21. FUNCTION Proportion#
  22.     DIM Delta1, Delta2
  23.     SHARED iValue, iMin, iMax
  24.     SHARED iNewMin, iNewMax
  25.     ' Delta1:Delta2 = iValue : iValue2
  26.     ' iValue2 = (Delta2 * ivalue) /Delta1
  27.     Delta1 = iMax - iMin
  28.     Delta2 = iNewMax - iNewMin
  29.     Proportion# = (iValue * Delta2) / Delta1
  30.  
If you change the STEP of FOR to 0.6 or 0.8 you get more different values
Thanks for feedback I love to know your opinion on this last issue (proportion vs normalization)

Programming isn't difficult, only it's  consuming time and coffee

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Hi TempodiBasic,

Looks like Fellippe's is the only one that is working correctly, yours don't seem capable of negative scales and are knocked out when divided by 0 as mentioned by Mr Frost:
Code: QB64: [Select]
  1. DIM iValue AS SINGLE, iMin AS SINGLE, iMax AS SINGLE
  2. DIM iNewMin AS SINGLE, iNewMax AS SINGLE
  3. DIM dNewValue AS DOUBLE, dNewValue2 AS DOUBLE
  4.  
  5.  
  6. iMin = 0
  7. iMax = 10
  8. iNewMin = -100
  9. iNewMax = 0
  10. PRINT " StartValue    Proportion    Translation"
  11. FOR i = 2 TO 7 STEP .7
  12.     iValue = i
  13.     dNewValue = Proportion#
  14.     dNewValue2 = Normalize#
  15.     PRINT iValue, dNewValue, dNewValue2, map!(iValue, iMin, iMax, iNewMin, iNewMax)
  16.  
  17. END ' local end of the program
  18.  
  19. FUNCTION Proportion#
  20.     DIM Delta1, Delta2
  21.     SHARED iValue, iMin, iMax
  22.     SHARED iNewMin, iNewMax
  23.     ' Delta1:Delta2 = iValue : iValue2
  24.     ' iValue2 = (Delta2 * ivalue) /Delta1
  25.     Delta1 = iMax - iMin
  26.     Delta2 = iNewMax - iNewMin
  27.     Proportion# = (iValue * Delta2) / Delta1
  28.  
  29. FUNCTION Normalize#
  30.     SHARED iValue AS INTEGER, iMin AS INTEGER, iMax AS INTEGER
  31.     SHARED iNewMin AS INTEGER, iNewMax AS INTEGER
  32.  
  33.     'valore normalizzato =  minimoscala+
  34.     '((osservazione-MIN(intervallo))/
  35.     '(MAX(intervallo)-MIN(intervallo))*
  36.     '(massimoscala-minimoscala)
  37.  
  38.     Normalize# = iNewMin + ((iValue - iMin) / (iMax - iMin) * (iNewMax - iNewMin))
  39.  
  40.  
  41. FUNCTION map! (value!, minRange!, maxRange!, newMinRange!, newMaxRange!)
  42.     map! = ((value! - minRange!) / (maxRange! - minRange!)) * (newMaxRange! - newMinRange!) + newMinRange!
  43.  


« Last Edit: October 17, 2020, 01:55:33 pm by bplus »

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
@Richard Frost
I'm sorry to make this mistake about "i" prefix!
I'll correct the typemismatch as soon as I can!

I agree totally about the issue of division by zero, but in this case the range is not a range because imin == imax  && inewmin == inewmax
if only one of the extreme points of the range is 0 it's not matter

Here the Proportion# function in one line
Code: QB64: [Select]
  1. DIM iValue AS SINGLE, iMin AS SINGLE, iMax AS SINGLE
  2. DIM iNewMin AS SINGLE, iNewMax AS SINGLE
  3. DIM dNewValue AS DOUBLE, dNewValue2 AS DOUBLE
  4.  
  5.  
  6. iMin = 1
  7. iMax = 10
  8. iNewMin = 10
  9. iNewMax = 100
  10. PRINT " StartValue    Proportion    Translation"
  11. FOR i = 2 TO 7 STEP .6
  12.     iValue = i
  13.     dNewValue = Proportion#
  14.     dNewValue2 = Normalize#
  15.     PRINT iValue, dNewValue, dNewValue2
  16.  
  17.  
  18.  
  19. END ' local end of the program
  20.  
  21. FUNCTION Proportion#
  22.     '    DIM Delta1, Delta2
  23.     SHARED iValue, iMin, iMax
  24.     SHARED iNewMin, iNewMax
  25.     ' Delta1:Delta2 = iValue : iValue2
  26.     ' iValue2 = (Delta2 * ivalue) /Delta1
  27.     '   Delta1 = iMax - iMin
  28.     '  Delta2 = iNewMax - iNewMin
  29.     Proportion# = (iValue * (iNewMax - iNewMin)) / (iMax - iMin)
  30.  
  31. FUNCTION Normalize#
  32.     SHARED iValue, iMin, iMax
  33.     SHARED iNewMin, iNewMax
  34.  
  35.     'valore normalizzato =  minimoscala+
  36.     '((osservazione-MIN(intervallo))/
  37.     '(MAX(intervallo)-MIN(intervallo))*
  38.     '(massimoscala-minimoscala)
  39.  
  40.     Normalize# = iNewMin + ((iValue - iMin) / (iMax - iMin) * (iNewMax - iNewMin))
  41.  

About your opinion how is significative the difference of results of the two function?
Programming isn't difficult, only it's  consuming time and coffee

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Hi Bplus
glad to get your feedback

the code posted by you for comparison among proportion#, Normalization# and the superlative PMAP! gives to me this result

 
BestFellippePMAP.jpg


I cannot see the difference for now. However my goal is not to post a duplicate  (better or worse than) PMAP! of Fellippe, but to evaluate if the difference got with the 2 methods is significant or not for ordinary calculation, because I think that it is important for calculation of NASA. As you can remember the proportion method has been used by Talete from Mileto to calculate the radium of the earth using the pyramid of Aegipt and a pole.  On the other hand Normalization is a statistical method.
Thaks to talk about this.
Programming isn't difficult, only it's  consuming time and coffee

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Here's what I got from code I posted, I copy pasted into QB64 IDE from forum looks OK to me:
 
result.PNG


Running in Windows 10-64 laptop QB64 v 1.4 stable

Quote
(better or worse than) PMAP! of Fellippe,
PS not using PMAP, using Fellippe's map! function.

Quote
because I think that it is important for calculation of NASA.
:-)) I am thinking if NASA used your code they might be firing rockets into the center of the earth!

« Last Edit: October 17, 2020, 02:35:39 pm by bplus »

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
@bplus
yes you're right PMAP is a QB45 keyword, that of Fellippe & Ashish is map!, but I have it in so much consideration that I have made a Freudian's lapsus.

so you're thinking that the earth is hollow... mmmh but in this case it is simpler to reach the center of the earth by pole's hole,is it? :))  Nevertheless I can pass my code to the NASA if you think that this is useful.

about my  C++ compiling error, in the following attemps I got your results.... QB64 1.5 dev in Windows 8 Pro 64bits.

My curiosity is about the result of Normalization#... nan? Is it an alien number that comes out?
However thanks Bplus you let see nearer my code so I see now that I have translate bad this template formula
Code: QB64: [Select]
  1.     'valore normalizzato =  minimoscala+
  2.     '((osservazione-MIN(intervallo))/
  3.     '(MAX(intervallo)-MIN(intervallo))*
  4.     '(massimoscala-minimoscala)
with this code
Code: QB64: [Select]
  1.     Normalize# = iNewMin + ((iValue - iMin) / (iMax - iMin) * (iNewMax - iNewMin))
as you can see the last rounded parenthesis must be put  after (imax-iMin) and before * (iNewMax-iNewMin)!
a typo error!

about proportion# it has been build only for positive numbers...
but if we want adapt it to all combinations (like your example where it manages negative numbers) we must use the ABSolute value of the variable passed to it and adding at the end the iNewMin because the counting of numbers starts from there.
So here the code!
Code: QB64: [Select]
  1. DIM iValue AS SINGLE, iMin AS SINGLE, iMax AS SINGLE
  2. DIM iNewMin AS SINGLE, iNewMax AS SINGLE
  3. DIM dNewValue AS DOUBLE, dNewValue2 AS DOUBLE
  4.  
  5.  
  6. iMin = 0
  7. iMax = 10
  8. iNewMin = -100
  9. iNewMax = 0
  10. PRINT " StartValue    Proportion    Translation"
  11. FOR i = 2 TO 7 STEP .6
  12.     iValue = i
  13.     dNewValue = Proportion#
  14.     dNewValue2 = Normalize#
  15.     PRINT iValue; " "; dNewValue; " "; dNewValue2; " "; map!(iValue, iMin, iMax, iNewMin, iNewMax)
  16.  
  17. END ' local end of the program
  18.  
  19. FUNCTION Proportion#
  20.     SHARED iValue, iMin, iMax
  21.     SHARED iNewMin, iNewMax
  22.     ' Delta1:Delta2 = iValue : iValue2
  23.     ' iValue2 = (Delta2 * ivalue) /Delta1
  24.     ' Delta1 = Absolute( iMax - iMin)
  25.     'Delta2 = Absolute(iNewMax - iNewMin)
  26.     Proportion# = (iValue * ABS(iNewMax - iNewMin)) / ABS(iMax - iMin) + iNewMin
  27.  
  28. FUNCTION Normalize#
  29.     SHARED iValue, iMin, iMax
  30.     SHARED iNewMin, iNewMax
  31.  
  32.     'valore normalizzato =  minimoscala+
  33.     '((osservazione-MIN(intervallo))/
  34.     '(MAX(intervallo)-MIN(intervallo))*
  35.     '(massimoscala-minimoscala)
  36.  
  37.     Normalize# = iNewMin + ((iValue - iMin) / (iMax - iMin)) * (iNewMax - iNewMin)
  38.  
  39.  
  40. FUNCTION map! (value!, minRange!, maxRange!, newMinRange!, newMaxRange!)
  41.     map! = ((value! - minRange!) / (maxRange! - minRange!)) * (newMaxRange! - newMinRange!) + newMinRange!
  42.  

in this you can see that the differences between Normalize# and map! are apparents and not real, the only that stands still on is that normalize gives a double type back while map gives a single type back.

Now that you have helped me to correct my first code... do you want say me your opinion about Proportion method vs Normalize method?
Programming isn't difficult, only it's  consuming time and coffee

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Quote
Now that you have helped me to correct my first code... do you want say me your opinion about Proportion method vs Normalize method?

Hi TempodiBasic,

I rewrote each equation using like terms and applied Algebra
(ABS was not needed I am pretty sure in proportion.)

They worked out to this
Code: QB64: [Select]
  1. Proportion# = (NewMax - NewMin) * (Value - 0) / (Max - Min) + NewMin
  2.  
  3. Normalize# = (NewMax - NewMin) * (Value - Min) / (Max - Min) + NewMin
  4.  
  5. map! = (NewMax - NewMin) * (Value - Min) / (Max - Min) + NewMin
  6.  
  7.  
  8.  
  9. I would start like this:
  10.  
  11. something is to a min of a total range as something else is to another min of another different total range
  12.  
  13. (Value - Min) / (Max - Min) = (X - newMin) / (newMax - newMin)  solve for x
  14.  
  15. (newMax - newMin) * (Value - Min) / (Max - Min)  = X - newMin
  16.  
  17. (newMax - newMin) * (Value - Min) / (Max - Min) + newMin = X   or
  18.  
  19. X = (newMax - newMin) * (Value - Min) / (Max - Min) + newMin
  20.  
  21. QED
  22.  

Normalize is identical to map and proportion only works if Min = 0

So between Proportion and Normalize, NASA engineers prefer Normalize 99.99 %  ;-))


But hey!  What if all Mins are 0 which is very likely case with lengths of things then our formula simplifies to

X = newMax * Value / Max 
or
X is to NewMax AS Value is to Max

which is what Proportional means to me.

« Last Edit: October 17, 2020, 08:34:09 pm by bplus »