Talk:Q (number format)

From Wikipedia, the free encyclopedia

It needs more work; the introduction assumes too much knowledge. The Q number does not carry the field size. Q numbers get used even if the processor has a floating point unit. Another day. Charles Esson 23:04, 8 April 2007 (UTC)

I think this was invented by TI; but we need a reference to say it.Charles Esson 11:52, 10 April 2007 (UTC)

Contents

[edit] Range Error in Article

I dispute the following statement in the article:

For a given Q format, using an N-bit signed integer container with Q fractional bits:

  • Its range is [-2N-1-Q, 2N-1-Q-1]

A common usage is storing a Q15 value in a 16-bit signed integer object, so we have N=16 and Q=15. According to the article, the range would be [-216-1-15, 216-1-15-1] or [-20, 20-1] or [-1, 0] which, of course, is incorrect. The correct range is [-1, 0.99996948]. —Ksn 21:05, 16 April 2007 (UTC)

  • It is my view ( not worth much); your both right in a way. I think the article ( or at least the formula) is referring to the integer range. Your referring to the real range. I wonder what to do about it, cause your right it is not clear.Charles Esson 08:47, 18 April 2007 (UTC)
  • I added integer for now, but I think your right it has to be fixed. Charles Esson 08:54, 18 April 2007 (UTC)
  • Fixed it.Charles Esson 09:24, 18 April 2007 (UTC)

Thanx for the fix. It didn't make much sense to present the range in terms of integers when the point of the Q format is to express real numbers. —Ksn 00:02, 20 April 2007 (UTC)

[edit] Proposal to Dereference Referenced Paper

I propose that the external link to the paper Fixed Point Representation And Fractional Math be removed as it is not authoritative and contains errors, for example:

  • p. 2, after talking about using two's complement format it gives an example of an 8-bit value being specified as Q3.5, which does not accommodate the sign bit.
  • p. 2, it asserts that a C "int" is 16 bits, contrary to its actual definition; furthermore, int's are increasingly implemented as 32 bits.
  • p. 3, it gives the incorrect inequality "0 ≤ a ≤ 2QI", where the second "≤" should be "<".
  • p. 3, the equation "QI = ceiling(log2(abs(a)))" is incorrect for the same edge condition.
  • P. 3, it then presents different formulae when discussing the impact of signed numbers, but no change is necessary because QI is defined as being the number of integer bits, which implies not including the sign bit.

I didn't see the need to review the document further. —Ksn 13:56, 20 April 2007 (UTC)

  • I haven't read the document but I agree with your points.Charles Esson 06:08, 25 April 2007 (UTC)

These issues appear to have been addressed in a new release of the referenced paper User:anonymous —Preceding unsigned comment added by 128.104.188.119 (talk) 21:48, 30 August 2007 (UTC)

[edit] Using m and n instead of Q in the Math section; mixed fractional sizes in multiplication and division.

I've changed the first half of the article to uniformly use m and n (for a Qm.n format) instead of introducing Q and N variables. I think the math section that follows should follow suit, but I disagree with the statement that multiplication and division require the number of fractional digits in the dividend to be the same. Multiplying a Qa.b format number by a Qc.d format number can be done naturally by treating the Q format numbers as signed integers, and it will generally give a Qa+c.b+d format number. Division I'm not as sure about; I expect that Knuth's The Art of Computer Programming Volume 2 would have all the answers. Wdfarmer 04:06, 25 April 2007 (UTC)

  • If you don't keep the fractional digits the same then you change the type of Q number you are dealing with (as you have pointed out). Lets say you have Q14.17 by Q14.17, you end up with Q28.34, bit hard to fit it in a 32 bit register. If you don't fix up your base the division result is the different Q number(Qa-c.b-c); not the same Q number once again. Now if you going to change Q number type with multiplication and division than the statement 'resolution is constant' is wrong, resolution is only constant if you maintain the Q number type. What I have provided is a consistent set of operators that maintain the Q number type you start with and highlighted the need for rounding care. I think that is a lot more helpful than saying something along the line "If you don't fix you base the number will underflow or overflow". Charles Esson 06:04, 25 April 2007 (UTC)
  • Altered article to reflect your concern; there probable should be another section on treating m and n as indexes.Charles Esson 06:38, 25 April 2007 (UTC)

[edit] C sample code

There are more problems here than there are lines of code. I suspect it was written by someone who doesn't actually write C. Here are the issues, in descending severity:

  • The attempt to handle overflow doesn't actually do so. Assigning the result of a * b to a longer type doesn't matter; the overflow has already happened. You have to cast a or b before the multiplication.
  • The code also assumes that long is larger than int. On most current platforms, they're the same size.
  • Q is not defined anywhere in the code, so this won't compile.
  • More importantly, Q is not defined anywhere in the article, so a reader has to guess what it is. It's not hard to figure out that it's the denominator, which is refered to as "n" through most of the article, but a reader shouldn't have to figure this out.
  • The code is not valid C89, because it uses C++-style (//) comments. It may be valid C99, or C++, or C89 plus Microsoft or gcc extensions, but when people say "C" they generally mean C89.
  • If the code is meant to be C99, C++, VC, or gcc code, it's not idiomatic; variables should be declared at initialization rather than all together at the top.
  • The type "int" is already signed, so "signed int" is redundant, and likely to be confusing to the occasional C programmer, who will expect that it means something different from the normal int". The type "long int" is the same as "long." Although this one isn't as likely to confuse anyone, it's still verbose without adding anything.
  • The comment "2**(Q-1)" isn't going to help a C programmer, as there is no ** exponentiation operator in C.
  • K is clearly meant to be a constant. So, why not define it as such? Or, even better, give it a name?
  • C has this fancy new feature called "functions" that allow you to wrap up blocks of reusable code and give them a name. You're also allowed to give variables names longer than one letter.
  • Why "temp = temp + K" instead of "temp += K"?
  • Instead of declaring a "result" variable, why not just show these functions as functions?
  • Most modern compilers will spit out warnings about sticking a long value in a shorter type without an explicit cast or some other way to show the compiler that you know what you're doing.

Here's a suggestion:

static const short Q15_N = 15; /* fractional bits, n in a Q15 or Qm.15 format */

short Q15_add(short a, short b) {
  return a+b;
}

short Q15_subtract(short a, short b) {
  return a-b;
}

short Q15_multiply(short a, short b) {
  /* Rounding: mid values are rounded up */
  static const short Q15_ONE_HALF = 1 << (Q15_N - 1);
  long resultTimes2N = (long)a * b + Q15_ONE_HALF;
  /* Correct by dividing by base */
  return (short)(resultTimes2N >> Q15_N);
}

short Q15_divide(short a, short b) {
  /* pre-multiply by the base */
  long aTimes2N = (long)a << Q15_N;
  /* So the result will be rounded; mid values are rounded up */
  long roundedATimes2N = aTimes2N + b/2;
  return (short)(roundedATimes2N / b);
}

This still isn't really safe, as short isn't guaranteed to be smaller than long--but I can't think of any platforms where it isn't. (If you're worried, #if sizeof(short) == sizeof(long) #error "Wow!" #endif...) --75.36.132.72 11:28, 28 July 2007 (UTC)