Shop OBEX P1 Docs P2 Docs Learn Events
Calculation with multiple integers — Parallax Forums

Calculation with multiple integers

PlaneTeeRPlaneTeeR Posts: 100
edited 2006-05-31 22:53 in General Discussion
Hello,

For my project I have to make an average speed calculation. This I have to do with distance/time. But my program has multiple integers that represent the distance and time.

distance has two integeres (Km and m).
time has three integers (hours, minutes and seconds).

When I add them two one integer my range is limited (37,767), that means distance max 37KM and time max 10 hours.

How can i do this without these limitations?

Johnny

Comments

  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-05-26 13:00
    You must keep the two integers and combine them for printing only,
    then your range is 65535.999 km. If you want even larger integers
    you can use the Int32 class.
    (with the Format class you can print unsigned integers hence 65535)

    The only option for high numbers in a single integer is the fp3 class.
    This is a floating point number with only 3 digits: range up to 0.999E+15
    (E stands for power of 10). For example:·0.999E+00 km (999 m) or 0.999E+03 km (999 km)
    but I don't think you want that for your display.

    regards peter
  • PlaneTeeRPlaneTeeR Posts: 100
    edited 2006-05-26 13:04
    But how do i calculate with these seperate integers?

    2 voor distance 3 for time

    distance / time = avg

    Johnny
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-05-26 13:25
    To calculate the average speed avg:

    avg [noparse][[/noparse]m/s] = (1000*km + m) / (3600*hours + 60*minutes + seconds)

    avg [noparse][[/noparse]km/h] = (km + m/1000) / (hours + minutes/60 + seconds/3600) =
    ················· (intnom + frnom/65536)/(intden + frden/65536)

    minutes/60 and seconds/3600 are fractions (0 < value < 1)
    m/1000 is also a fraction

    frmin = UnsignedIntMath.ufrac(minutes,60);
    frsec = UnsignedIntMath.ufrac(seconds,3600);
    intden = hours; //integer of denominator
    frden = frmin + frsec; //fraction of denominator
    if (CPU.carry()) intden++;
    frnom = UnsignedIntMath.ufrac(m,10000); //fraction of nominator,·m is 0.1m units
    intnom = km; //integer of nominator

    Now we only need to rearrange the formula to calculate avg [noparse][[/noparse]km/h].
    I have to think about·how this can·be approximated easily.

    regards peter
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-05-26 13:51
    Here is another approach:
    Keep the average updated every loop:

    ·············+---+ speed
    avgold
    +···|
    ·············|·· |
    ·············|·· |
    ···· 0
    ······ 0·····T1· T2

    avgold is the·average speed for all previous loops,
    speed is the speed for the current loop
    T2-T1 is the time for the current loop
    T1 is the realtime for all previous loops
    T2 is the new realtime

    Then avgnew = ( (T1*avgold) + (T2-T1)*speed ) / T2
    = (T1/T2)*avgold + ((T2-T1)/T2)*speed

    T1/T2 is a fraction, as is (T2-T1)/T2
    These fractions are multiplied by integers.
    So this can be calculated using the UnsignedIntMath methods ufrac() and umulf().

    regards peter
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-05-26 14:28
    Some thoughts about the last approach:

    If the looptime is about 10 msec every loop,
    then T1/T2 equals 1 after T2=65536*10mSec = 655.36Sec = approx.·11 minutes.
    So after 11 minutes realtime, T1/T2 reaches 1
    But then (T2-T1)/T2 reaches 0
    so avgnew = avgold

    Conclusion: after about 11 minutes the average speed will not change.
    This is of course due to the 16bit math.
    You could of course use Float32 but I wonder if that would make
    much difference, unless the speed really increases or decreases after
    11 minutes.
    Another option is to scale down·T1,·T2 and (T2-T1) by a factor 10
    (after 11 minutes) and then perform the calculations. This would ensure
    the parameters are kept in the right range.

    regards peter

    Post Edited (Peter Verkaik) : 5/26/2006 2:58:35 PM GMT
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-05-26 15:08
    After some thinking, scaling down T1 and T2 will not work.
    The solution is to use larger time units for calculating the average
    speed. Say you calculate the average for the last 5 seconds
    and assume this is the speed for the current loop.
    Then recalculate T1 and T2 in 5sec units. (T2-T1 then equals 1)
    The above approach then works until
    T2 = 65536*5Sec = 327680Sec = 91 hours.
    I don't think you cycle that long!
    It does mean your average speed display is only updated every 5 seconds.

    regards peter


    Post Edited (Peter Verkaik) : 5/26/2006 3:14:08 PM GMT
  • PlaneTeeRPlaneTeeR Posts: 100
    edited 2006-05-26 15:58
    wow difficult i see, i will look into it and tell you how it comes out, i really need to concentrate on this smilewinkgrin.gif .

    Thanks again for this info burger.gif .

    Johnny
  • PlaneTeeRPlaneTeeR Posts: 100
    edited 2006-05-31 10:02
    What do you suggest that I do, with this calculation when using multiple classes?

    I now use sensor to keep track of number of pulses which in processor class be calculated into dstm / dstKm. And there we have the chronometer of seconds minutes and hours. I'm now not using the loop. But a method to calculate the average speed.

    Johnny
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-05-31 10:20
    In my opinion the speed must be calculated in the sensor class.
    Ideally you would want a sensor that gives you the speed
    at the moment you poll your sensor.
    So have a method int getSpeed() in your sensor class.

    Distance and average speed should be calculated in your application class (Main).

    I noticed you create a new Display() in your main class and then
    your mainloop starts in display.
    I think you must restrict Display to just do the printing to your display.
    After all, your display class should be independant of your current application.

    It is your application class that should create instances of your objects (display,sensor,buttons,uarts,timers)
    and then process and control information you get from those objects.

    That way your library classes (display,sensor) are independant of the current application
    and can then be reused by other applications.

    Edit:
    You can calculate distance and average speed also in your sensor class
    based on passed time between polls. Then those functions are also
    independant of your current application. And these two properties are
    closely related to your sensor.
    Or put those calculations in a seperate class so they can be reused
    when getting speed from an other source than your sensor.


    regards peter

    Post Edited (Peter Verkaik) : 5/31/2006 10:26:03 AM GMT
  • PlaneTeeRPlaneTeeR Posts: 100
    edited 2006-05-31 12:25
    Why calculate speed in the sensor? It becomes slower with calculations. My idea is all calculations in processor, so its linked this way (see pic).

    When you want to display the speed the application starts calculation in processor which retreives the current pulseTime and calculates..

    That should work fine doesn't it?
    650 x 508 - 23K
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-05-31 12:33
    I have made a start with a travel class.
    This class (for the math package) calculates
    distance based on speed and time
    speed based on distance and time

    Since these calculations are just a mathematical issue,
    I think it is wise to have them in a seperate class
    so other applications can use it also.

    It is by no means correct or complete
    but it lets you concentrate on the math only.
    I have defined the units which give the
    best possible range using integers.

    Problems arise when time,·speed or distance are very small
    so it probably is best to include some·methods
    that accumulate results until the results are within the
    range of preferred units.

    This class can be tested with just a javelin. No external hardware required.
    I will keep working on this. Please post any solutions you find.

    regards peter
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-05-31 12:42
    What makes you think things get slower if speed (in km/h) is
    calculated in the sensor class rather than the processor class?
    That really isn't an issue.
    It is much better to have more small classes than a few classes
    that integrate everything.
    The travel class in my previous post for example, is very small
    and handles a small part of your application, but it is in no way
    dependant of your application.
    That is what object oriented programming (OOP) is all about.

    regards peter
  • PlaneTeeRPlaneTeeR Posts: 100
    edited 2006-05-31 13:04
    How are you going around the problem that you have with the 16 bit integers when calculating for example avg speed.

    When distance is in two seperate ints and time in 3.·The limit of 16 bit is really irritant!

    Johnny
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-05-31 13:43
    You could use the Float32 class but that really is a big and slow class.
    Since both speed and average speed are in 0.01 km/h units it is possible
    to calculate these results using 16bit math by using fractions and
    rearranging the calculations.
    Like I said, this is a mathematical problem that really is independant
    of your particular application.
    I wrote out how to calculate distance in 0.1m units using speed in 0.01km/h units
    and time in ms units.

    distance[noparse][[/noparse]0.1m] = 100 * distance[noparse][[/noparse]0.01km]
    ···················· = 100 * speed[noparse][[/noparse]0.01km/h] * time[noparse][[/noparse]h]
    ···················· = 100 * speed[noparse][[/noparse]0.01km/h] * (1/60) * time[noparse][[/noparse]m]
    ···················· = 100 * speed[noparse][[/noparse]0.01km/h] * (1/60) * (1/60000) * time[noparse][[/noparse]ms]

    The trick is now to do these calculations in 16bit math without over- or underflow.
    The class UnsignedIntMath should be able to solve this. I am working on this.
    For example, speed=30000 (300 km/h) and time=30000 (30 sec) results
    in 25000 (2500 m).

    Obviously if time exceeds its limit then other units must be used.
    so multiple methods for different units may be necessary.


    regards peter
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-05-31 15:51
    I did it for the distance.
    You can run the attached test program to see calculated distances
    in 0.1m units for several given speed[noparse][[/noparse]0.01km/h] and time[noparse][[/noparse]ms] values.

    Here is the output of the test program:

    distance[noparse][[/noparse]0.1m] = speed[noparse][[/noparse]0.01km/h] * time[noparse][[/noparse]ms]
    distance[noparse][[/noparse]0.1m] = 30000 * 30000 = 25000
    distance[noparse][[/noparse]0.1m] = 10000 * 30000 = 8333
    distance[noparse][[/noparse]0.1m] = 3000 * 30000 = 2500
    distance[noparse][[/noparse]0.1m] = 1000 * 30000 = 833
    distance[noparse][[/noparse]0.1m] = 30000 * 10000 = 8333
    distance[noparse][[/noparse]0.1m] = 10000 * 10000 = 2778
    distance[noparse][[/noparse]0.1m] = 3000 * 10000 = 833
    distance[noparse][[/noparse]0.1m] = 1000 * 10000 = 278
    distance[noparse][[/noparse]0.1m] = 30000 * 3000 = 2500
    distance[noparse][[/noparse]0.1m] = 10000 * 3000 = 833
    distance[noparse][[/noparse]0.1m] = 3000 * 3000 = 250
    distance[noparse][[/noparse]0.1m] = 1000 * 3000 = 83
    distance[noparse][[/noparse]0.1m] = 30000 * 1000 = 833
    distance[noparse][[/noparse]0.1m] = 10000 * 1000 = 278
    distance[noparse][[/noparse]0.1m] = 3000 * 1000 = 83
    distance[noparse][[/noparse]0.1m] = 1000 * 1000 = 27
    program finished

    regards peter
  • PlaneTeeRPlaneTeeR Posts: 100
    edited 2006-05-31 19:57
    Hmmm i can't follow you on this, how does this solve my problem with having 2 ints for distance and 3 for time > for measuring the average speed?
  • Peter VerkaikPeter Verkaik Posts: 3,956
    edited 2006-05-31 22:53
    I added the code for calculating speed, time and average.
    Note that average is speed but uses different units for distance and time.

    For average:
    The distance units are 10m, the time units are seconds.
    Using positive integers that means distance has a range of 32767*10m = 327.67km
    and time has a range of 32767*1s = 9.1h

    If your application has stored hours, minutes and seconds
    (I assume you have stored distance in 0.01km units = 10m units)
    you use averageSpeed = travel.average(distance,(60*hours+minutes)*60+seconds)

    If you have stored the distance in two integers dstKm[noparse][[/noparse]km] and dstm[noparse][[/noparse]0.1m] then use
    distance = dstKm*100+(dstm/100) in the above formula.

    regards peter



    Post Edited (Peter Verkaik) : 6/1/2006 6:23:59 AM GMT
Sign In or Register to comment.