почему умножение Q.15 не работает

Ссылаясь на обозначение для представления с фиксированной точкой, я пытался следовать, но я совсем запутался.

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

выход

((0.2929 * q)) = cc60

Я ожидаю увидеть 257d, потому что из калькулятора 0.2929 * 32768 in hex = 257d

В чем проблема использовать этот формат Q.15, или это только из-за неправильной печати


РЕДАКТИРОВАТЬ

Ребята, на самом деле я никогда не думал об этом.

Мой фактический код пытается напечатать два значения. Я думал, что печать второго значения - это проблема. После комментариев @Soren я скопировал его код и работает. Затем я удалил 1-е значение из printf, мой код также сработал. Итак, я публикую оператор printf

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)));

где вторая строка предложена Сероном.

The value of sys3.b0 = 0.0000000001295

Теперь выход

(sys3.b0 * q) = 4DB173CF        ((0.2929 * q)) = 3ED1CC60
(sys3.b0 * q) = 257D

person nmxprime    schedule 21.03.2014    source источник


Ответы (2)


У вас есть неопределенное поведение в результате:

0.2929 * q

является двойным, но вы говорите printf, что это беззнаковое короткое замыкание. Если вы приведете результат к unsigned short, вы получите ожидаемый результат (увидеть его вживую):

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

Если предупреждение было включено или активировано, это должно было указывать на проблему, и gcc, и clang выдают одинаковые ошибки:

предупреждение: формат '%hx' ожидает аргумент типа 'int', но аргумент 2 имеет тип 'double' [-Wformat=]

Хотя судя по всему Visual Studio этого не делает.

person Shafik Yaghmour    schedule 21.03.2014
comment
я в среде MS VC++, и все предупреждения. приведение типов по-прежнему приводит к тому же результату - person nmxprime; 21.03.2014
comment
@nmxprime Я добавил живой пример, в котором этот код правильно работает в Visual Studio. - person Shafik Yaghmour; 21.03.2014
comment
@nmxprime все еще не определено изменение поведения с (sys3.b0 * q) на (unsigned)(sys3.b0 * q) - person Shafik Yaghmour; 21.03.2014
comment
Спасибо! Хорошо, но есть намек на это необычное поведение? может быть способ Windows сделать? Теперь у меня нет компьютера с Linux, чтобы проверить его с помощью gcc. - person nmxprime; 21.03.2014
comment
@nmxprime вы можете использовать как gcc, так и clang через один из множества доступных онлайн-компиляторов. Неопределенное поведение означает, что поведение непредсказуемо, когда вы указываете %X, но передаете double, скорее всего, printf берет мусорные значения из стека или, возможно, регистров, поскольку double обычно больше, чем unsigned. - person Shafik Yaghmour; 21.03.2014
comment
Большое спасибо!! Принимаю ваш ответ, так что эта тема может быть закрыта !! - person nmxprime; 21.03.2014

Строка формата ожидает тип, отличный от того, который вы фактически ей даете. Мой компилятор говорит:

foo.c:5:33: предупреждение: формат указывает тип «беззнаковый короткий», но аргумент имеет тип «двойной» [-Wformat]

Итак, вам нужен приведение для преобразования 0.2929 * q из double в unsigned int. Так:

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

РЕДАКТИРОВАТЬ: Когда вы подаете printf аргумент неправильного типа, он будет читать только столько байтов, сколько он думал получить. В твоем случае:

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

Строка формата говорит ожидать два unsigned int, то есть два раза по 4 байта*. Но вы дали ему double и unsigned int, что соответственно 8 и 4 байта*. printf просто считывает 4 байта для каждого %X, поэтому он эффективно считывает 8-результат sys3.b0 * q, считая эти 8 байтов двумя целыми числами, которые затем печатает.

person Søren Debois    schedule 21.03.2014
comment
(unsigned)((0.2929 * q)) по-прежнему дает тот же результат. я использую MS VС++ - person nmxprime; 21.03.2014
comment
изменение %hx на %x дает 3ed1cc60 - person nmxprime; 21.03.2014
comment
Странный. Может быть, попробовать скопировать мою программу выше, чтобы убедиться, что там нет опечатки? - person Søren Debois; 21.03.2014
comment
ваша программа работает!! После тестирования я обнаружил еще более странную вещь! Позвольте мне отредактировать вопрос соответственно - person nmxprime; 21.03.2014