Question

Refering Notation for fixed point representation i have tried following, but i am totally confused.

int q = 1<<15;
printf("(sys3.b0 * q) = %hx \n",((0.2929 * q)));

output is

((0.2929 * q)) = cc60

I expect to see 257d because from calculator, 0.2929 * 32768 in hex = 257d

What is the problem in using this Q.15 format, or is this just because of not properly printing


EDIT

Guys, actually i've never thought of it.

My actual code tries to print two values. I thought 2nd value printing is the problem. After comments of @Soren i copied his code and is working. Then i removed 1st value from printf, my code also worked. So i repost the printf statement

printf("(sys3.b0 * q) = %X \t((0.2929 * q)) = %X\n",(sys3.b0 * q),(unsigned)((0.2929 * q)));
printf("(sys3.b0 * q) = %X \n",((unsigned)(0.2929 * q)));

where the second line is as suggested by Seron.

The value of sys3.b0 = 0.0000000001295

Now the output is

(sys3.b0 * q) = 4DB173CF        ((0.2929 * q)) = 3ED1CC60
(sys3.b0 * q) = 257D
Was it helpful?

Solution

What you have is undefined behavior the result of:

0.2929 * q

is a double but you are telling printf it is a unsigned short. If you cast the result to unsigned short you will get the result you expect (see it live):

printf("(sys3.b0 * q) = %hx \n",(unsigned short)(0.2929 * q));
                                ^^^^^^^^^^^^^^^^

Having warning turned on or up should have indicated that this was a problem, both gcc and clang give similar errros:

warning: format '%hx' expects argument of type 'int', but argument 2 has type 'double' [-Wformat=]

Although apparently Visual Studio does not.

OTHER TIPS

The format string expects a type different from the one you're actually giving it. My compiler says:

foo.c:5:33: warning: format specifies type 'unsigned short' but the argument has type 'double' [-Wformat]

So you need a cast to convert 0.2929 * q from a double to an unsigned int. Like this:

int main() {
    int q = 1<<15;
    printf("(sys3.b0 * q) = %X \n",((unsigned)(0.2929 * q)));
}

EDIT: When you feed printf an argument of the wrong type, it'll read only as many bytes as the type it thought it was getting. In your case:

printf("(sys3.b0 * q) = %X \t((0.2929 * q)) = %X\n",
       (sys3.b0 * q),
       (unsigned)((0.2929 * q)))

The format string says to expect two unsigned int, that is, two times 4 bytes*. But you gave it a double and an unsigned int, which are respectively 8 and 4 bytes*. printf just reads 4 bytes for each %X, so effectively it reads the 8-result of sys3.b0 * q, thinking those 8 bytes are two integers, which it then prints.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top