|
|
View previous topic :: View next topic |
Author |
Message |
evsource
Joined: 21 Nov 2006 Posts: 129
|
Faster computations |
Posted: Tue Nov 10, 2009 11:46 pm |
|
|
Hi,
I recently posted about faster computations. I have another question. With divide operations being so expensive, is there a better way to do the following:
x (a constant)
y (a constant)
z (obtained value that varies)
The equation: (x * y) / z
I can calculate ahead of time x * y, since these are constants. But with z being the variable, I can't see any way around the division.
Thanks in advance! |
|
|
Guest
|
|
Posted: Wed Nov 11, 2009 6:41 am |
|
|
Scott Edwards' Stamp application #9 has an article about using fast integer math which might help, but you'll have to compare with fp package. |
|
|
John P
Joined: 17 Sep 2003 Posts: 331
|
|
Posted: Wed Nov 11, 2009 10:55 am |
|
|
But if X and Y are constants, how can Z be anything but constant?
I tried adding this to a program I already had:
Code: |
#define X (float)1.234
#define Y (float)5.678
#define Z (float)(X/Y)
//Then later on, in the actual code:
float zz;
zz = Z;
|
This all compiled properly, and the "zz = Z" line generated some plausible looking assembly code. Have I misunderstood the problem? |
|
|
Douglas Kennedy
Joined: 07 Sep 2003 Posts: 755 Location: Florida
|
|
Posted: Wed Nov 11, 2009 11:28 am |
|
|
This issue involves basic math. In a world of numbers multiplication is exact and division is inexact unless the numerator is exactly divisible by the denominator. Now the PIC represents numbers in base 2 so if the divisor is a power of 2 then division reduces to shifting. Most often this isn't the case and can't be arranged by scaling the numerator in which case division becomes a highly optimized subtraction loop with variable timing depending on the relation between the numerator and the denominator. It's the way numbers are we all know from school that division was more laborious than multiplication. |
|
|
Ken Johnson
Joined: 23 Mar 2006 Posts: 197 Location: Lewisburg, WV
|
|
Posted: Wed Nov 11, 2009 3:04 pm |
|
|
Your are right, you must divide (somehow).
However, the compiler will compute (x * y) for you - you don't have to explicitly do that.
Ken |
|
|
Ttelmah Guest
|
|
Posted: Wed Nov 11, 2009 4:06 pm |
|
|
Let me give you a 'for instance' type example, that shows a way of saving time.
Imagine that you are getting a value from an ADC. Because if comes from a voltage source, that is 0 to 2.5v (say), you decide to scale to value as a floating point number 0-2.5, nd use a floating point division to do so. Then this value actually represents something else (perhaps a flow), so there is a scale factor that has to be applied to this final result. The flow (say) is actually 500l/min, for 1v, and you want to display an output representng the time needed for 1000l to pass. The maths then becomes:
1000/(500*v)
You want to output this in minutes, with two decimal places, so print this float out, with %5.2f
Now, at several points in this, you are making decisions. The initial conversion to a 'voltage' value, and then scaling everything to suit the 'thinking', and final result, rather than the processor.
If you start instead from the other end. You want only 2 decimal places.
v itself started as an integer, 0 to 1023. If you step 'back' from the problem, and look at only the two 'endpoint' numbers, you have:
1023 -> should display 0.8
1 -> 819.2
0 -> impossible
If you multiply by 81920, and perform just an integer division, from the original number, you get:
81920/1023 = 80
81920/1 = 81920
So, if you instead of doing the original conversion to 'volts', and then the scaling, and finally the floating point print:
if (adc_val==0) printf("No flow");
else printf("%6.2Lw",(int32)81920/adc_val);
You get the required result, using int32 divison, rather than float. Typically about 2/3rd the time, and remember this is also saved on the output of every digit to the display, as well as in the original calculation...
Now, this type of 'arithmetic re-thinking', is vital on anything involving speed. Going yet further, if you could work with only one decimal, the same operation could be repeated using int16, with the times improving by a futher factor of four.....
I'd suspect you may well be able to save a lot of time in your application, but it can only be done by knowing what the numbers represent, the likely ranges, and what final accuracy is required.
Best Wishes |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|