0

I want to divide a fixed-point number (Q31/int32 representing a fractional number with 31 fractional bits) by another Q31/int32. I want to calculate z = y/x, knowing that abs(x)>abs(y). Therefore, z<1 so it can be represented as another Q31/int32. So I thought I would need to left-shift Y by 32 bits, and cast it as an int64. Then I should be able to divide by an int32 (casting not necessary, but there for clarity) and cast back to an int32:

int32_t  x, y = ?? ;
int32_t  z = (int32_t)( ((int64_t)y<<32) / ((int32_t)x) );

But it doesn't work. Can you see any obvious error?

KamilCuk
  • 120,984
  • 8
  • 59
  • 111
iancl
  • 1
  • Possible duplicate of [Fixed Point Arithmetic in C Programming](https://stackoverflow.com/questions/10067510/fixed-point-arithmetic-in-c-programming) – paulsm4 May 12 '19 at 16:48
  • Och, I just found it out that the the explanation and example algorithms for Q number format can be found on [wiki](https://en.wikipedia.org/wiki/Q_(number_format)). – KamilCuk May 12 '19 at 16:48
  • OK, so with more testing, I found the failure point. This works: Decimal: 1937302376 / 926491996 = 2054017417 (Hex: 7378E368 / 3739 255C = 7A6D D189). And this doesn't: Decimal: 1805901494 / 1161997366 = -1531394255 (Hex: 6BA3 DEB6‬ / 4542 AC36 = A4B8 C731). So my error is when the answer will be >=0.5 or <0.5, due to the range of Q31. So I suppose I need to additionally divide by two (perhaps pre-multiplying x by 2 will be the fastest) and my result will be in Q1.30. – iancl May 12 '19 at 16:55
  • Actually, a better alternative is probably to right-shift the result one bit, before casting back from int64 to int32. – iancl May 12 '19 at 17:02

1 Answers1

0

My problem was that the two numbers are Q31 and I want a Q31 answer, so I actually need to have a Q1.62 numerator in my division. My code was effectively using a Q63 numerator, and dividing by Q31, and that ended up with a result which was limited to the range [-0.5,0.5) instead of [-1,1).

The solution is to bitshift by 31 instead of 32, to get the Q1.62 numerator, which makes much more sense now I think more about what I'm doing.

iancl
  • 1