unsigned long operations gives unexpected result

Hello, Unsigned long operations gives me an unexpected result. I need to make an operation (it's a linear interpolation but who care :) http://en.wikipedia.org/wiki/Linear_interpolation ) with longs and the results need to be long as well.

the result of y should be 13320 but it returns 4600 instead!

here is the code, thank you very much for your help

void setup() {

  Serial.begin(9600);

}

void loop() {
  unsigned long  xa, xb, ya, yb, x, y; //used for linear interpolation
  x = 4526;
  xa = 4400;
  ya = 13696;
  ya = 4600;
  yb = 13100;

  y = ya + ((x - xa) * ((yb - ya) / (xb - xa)));
  Serial.println(y);

  delay(1000);

}

Typo I expect. xb is never given a value, ya is assigned twice.

oups, indeed but still not working ! New result is 2705842654

void setup() {

  Serial.begin(9600);

}

void loop() {
  unsigned long  xa, xb, ya, yb, x, y; //used for linear interpolation
  x = 4526;
  xa = 4400;
  ya = 13696;
  xb = 4600;
  yb = 13100;

  y = ya + ((x - xa) * ((yb - ya) / (xb - xa)));
  Serial.println(y);

  delay(1000);

}

Try long instead of unsigned long. yb-ya is negative, which is likely causing your issue.

yb-ya is negative.

Getting closer! replacing unsigned long with long I got 13444 where 13320 will have been expected.

Replacing Long by float I got the 13320 (altought too slow in my context) the long approximation will be good enough

thx for your help

Yup, your "slope" calculation = 3.96, which will turn into 3.

roscodemars: Getting closer! replacing unsigned long with long I got 13444 where 13320 will have been expected.

Replacing Long by float I got the 13320 (altought too slow in my context) the long approximation will be good enough

If you can do so without causing an overflow then multiply the LONG values by 10 or 100 to preserve greater accuracy. Just remember that your result is too high.

...R

Or rearrange things to do the (x-xa) * (yb-ya) before dividing by (xb-xa)

Indeed, you should code it like this:

  y = ya + (x - xa) * (yb - ya) / (xb - xa) ;

What you really want is an implementation of muldiv (which would give the correct result even if the multiply result was larger than a long by using a 64 bit intermediate result).

  y = ya + muldiv (x-xa, yb-ya, xb-xa) ;

I don't know of a muldiv for Arduino, let along one for longs on Arduino.

you can add rounding at the cost of a division by 2 ...

y = ya + ((x - xa) * (yb - ya) + (xb-xa)/2) / (xb - xa) ;