Intermediate math question

I have an equation in a sketch that does not work unless I make or cast everything float.

bearing = 180 + 180 * (w1 - delta) / 1024 - (2 * delta)
(float)bearing = 180.0 + 180.0 * ((float)w1 - (float)delta) / 1024.0 - (2.0 * (float)delta)

The problem is with w1 = 339 and delta = 122 the intermediate total is .28 and in integer math 180 * .28 = 0
Is there a way around this or is just the way it is? I’m new to this so I’m sorry if this is obvious to all.

The downside to using floats is the amount of FLASH consumed by the code, and CPU time could be an issue. If those aren’t problems for you, just use floats.

One way to deal with it is to simulate fixed point by scaling the values by 10 or 100 - just multiple everything by the scale factor, do the math, then divide the result by the scale factor. e.g.:

#define SCALE 10
...
// not simplified, we'll make it readable and let the compiler optimize
bearing = (180 * SCALE + 180 * SCALE * (w1 * SCALE - delta* SCALE) / 1024 * SCALE - (2 * delta * SCALE))/ SCALE;

Of course, instead of explicitly scaling each value, you could store everything scaled.

-j

Thanks, I’ll work with that a bit. One problem though, if you scale all the parts the intermediate product is still .28. I’ll have to make sure I only scale some of the values. It’s doable though.

Had one more glitch… now some of my intermediates are larger than 32565 so I had to go with unsigned integers. Since all my numbers are (they better be or something is wrong) positive this isn’t a problem.

The problem is with w1 = 339 and delta = 122 the intermediate total is .28 and in integer math 180 * .28 = 0

I don’t believe this is true… The equation:

180 * (w1 - delta) / 1024

will result in the multiplication being carried out before the division, so with w1 = 339 and delta = 122, you will get

180 * (w1 - delta) / 1024
= 180 * 217 / 1024
= 39060 / 1024
= 38

The reason why this wasn’t working for you is that you were using signed integers, which means that 39060 evalutes to a -6293, which probably throws off your results. I assume you weren’t expecting 180 * (w1 - delta) / 1024 to evaluate to -6.

Using your original formulation with unsigned integers and without scale factors should work for you, assuming you’re happy with the resolution provided by integer math. If it’s possible for 180 * (w1 - delta) to be greater than 65535, you will need to convert one of the quantities to a long:

180UL * (w1 - delta)

  • Ben