Умножение чисел с фиксированной точкой - PullRequest
0 голосов
/ 13 марта 2020

У меня очень базовый c вопрос. В моей программе я делаю умножение двух чисел с фиксированной точкой, что приведено ниже. Мои входные данные имеют формат Q1.31, а выходные данные также должны быть в том же формате. Для этого я сохраняю результат умножения во временной 64-битной переменной, а затем выполняю некоторые операции, чтобы получить результат в требуемом формате.

int conversion1(float input, int Q_FORMAT)
{
return ((int)(input * ((1 << Q_FORMAT)-1)));
}

int mul(int input1, int input2, int format)
{
    __int64 result;
    result = (__int64)input1 * (__int64)input2;//Q2.62 format
    result = result << 1;//Q1.63 format
    result = result >> (format + 1);//33.31 format
    return (int)result;//Q1.31 format
}

int main()
{
    int Q_FORMAT = 31;
    float input1 = 0.5, input2 = 0.5;
    int q_input1, q_input2;
    int temp_mul;
    float q_muls;

    q_input1 = conversion1(input1, Q_FORMAT);
    q_input2 = conversion1(input2, Q_FORMAT);
    q_muls = ((float)temp_mul / ((1 << (Q_FORMAT)) - 1));
    printf("result of multiplication using q format = %f\n", q_muls);
    return 0; 
}

 My question is while converting float input to integer input (and also while converting int output 
 to float output), i am using (1<<Q_FORMAT)-1 format. But i have seen people using (1<<Q_FORMAT) 
 directly in their codes. The Problem i am facing when using (1<<Q_FORMAT) is i am getting the 
 negative of the desired result.

Например, в моей программе

 If i use (1<<Q_FORMAT), i am getting -0.25 as the result
 But, if i use (1<<Q_FORMAT)-1, i am getting 0.25 as the result which is correct.

Где я иду не так? Нужно ли понимать какие-либо другие понятия?

1 Ответ

1 голос
/ 14 марта 2020

На обычных платформах int - это 32-разрядное целое число из двух дополнений, содержащее 31 цифру (плюс знаковый бит). Он слишком узок, чтобы представлять число Q1.31, для которого требуется 32 цифры (плюс бит знака).

В вашем примере это проявляется как эффективное арифметическое c переполнение в выражении, 1 << Q_FORMAT.

Чтобы избежать этого, вам нужно либо использовать тип, содержащий больше цифр (например, long long), либо формат с фиксированной запятой, требующий меньше цифр (, например, Q1.30 ) , Вы можете использовать unsigned для исправления вашего примера, но результат будет немного «знаковым», чем Q2.30.

...