Арифметические значения с фиксированной точкой c в C? - PullRequest
0 голосов
/ 20 июня 2020

Как реализовать преобразование с плавающей точкой в ​​фиксированную точку, преобразование из фиксированной точки в преобразование с плавающей точкой, сложение / умножение с фиксированной точкой?

1 Ответ

0 голосов
/ 20 июня 2020

Чтобы использовать фиксированную точку, мы должны реализовать операции сложения и умножения. В этом случае нам нужно беспокоиться о том, сколько бит вы выделили для дробной части и сколько бит выделено для целой части. А затем мы можем выполнить операцию «сдвига» по вашему усмотрению.

В следующем фрагменте кода я реализовал фиксированную точку, выделив 22 бита для дробной части и 9 бит для целой части. (дополнительный бит будет для знака)

При умножении я сначала увеличил битовую длину каждого значения, чтобы избежать переполнения. После умножения сдвиг влево будет сохранять ту же дробную часть для вывода умножения.

Кроме того, я добавил насыщенность для вывода, чтобы избежать переполнения (если произойдет переполнение, то вывод сохранит максимальное абсолютное значение, которое он может сохранить независимо от знака)

#include <stdio.h>
#include <math.h>
#include <stdint.h>

#define fractional_bits 30
#define fixed_type_bits 32

typedef int32_t fixed_type;
typedef int64_t expand_type;

fixed_type float_to_fixed(float inp)
{
    return (fixed_type)(inp * (1 << fractional_bits));
}

float fixed_to_float(fixed_type inp)
{
    return ((float)inp) / (1 << fractional_bits);
}

fixed_type fixed_mult(fixed_type inp_1, fixed_type inp_2)
{
    fixed_type inp_1_sign = inp_1 >> (fixed_type_bits - 1);
    fixed_type inp_2_sign = inp_2 >> (fixed_type_bits - 1);
    fixed_type mult = (fixed_type)(((expand_type)inp_1 * (expand_type)inp_2) >> fractional_bits);
    fixed_type mult_sign = mult >> (fixed_type_bits - 1);

    if ((inp_1_sign != inp_2_sign && mult_sign == -1) || (inp_1_sign == 1 && inp_2_sign == 1 && mult_sign == 0) || (inp_1_sign == -1 && inp_2_sign == -1 && mult_sign == 0))
    {
        return mult;
    }
    else if ((inp_1_sign != inp_2_sign) && mult_sign == 0)
    {
        return (1 << (fixed_type_bits - 1));
    }
    else
    {
        return ((1 << (fixed_type_bits - 2)) - 1 + (1 << (fixed_type_bits - 2)));
    }
}

fixed_type fixed_add(fixed_type inp_1, fixed_type inp_2)
{
    fixed_type inp_1_sign = inp_1 >> (fixed_type_bits - 1);
    fixed_type inp_2_sign = inp_2 >> (fixed_type_bits - 1);
    fixed_type add = inp_1 + inp_2;
    fixed_type add_sign = add >> (fixed_type_bits - 1);

    if (inp_1_sign != inp_2_sign)
    {
        return add;
    }
    else if (add_sign == inp_1_sign)
    {
        return add;
    }
    else if (add_sign == -1)
    {
        return ((1 << (fixed_type_bits - 2)) - 1 + (1 << (fixed_type_bits - 2)));
    }
    else if (add_sign == 0)
    {
        return (1 << (fixed_type_bits - 1));
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...