简体   繁体   English

C 中的定点运算?

[英]Fixed point arithmetic in C?

How to implement floating-point to fixed-point conversion, fixed-point to floating-point conversion, fixed-point addition/multiplication?如何实现浮点到定点转换、定点到浮点转换、定点加法/乘法?

To use fixed-point, then we must implement addition and multiplication operations.要使用定点,那么我们必须实现加法和乘法运算。 In that case, we need to worry about how many bits you have allocated for the fractional part and how many bits allocated for the integer part.在这种情况下,我们需要担心您为小数部分分配了多少位以及为 integer 部分分配了多少位。 And then we can do "shift" operation as your preference.然后我们可以根据您的喜好进行“移位”操作。

In the following code-snippet, I've implemented fixed-point by allocating 22 bits for the fractional part and 9 bits for the integer part.在下面的代码片段中,我通过为小数部分分配 22 位和为 integer 部分分配 9 位来实现定点。 (additional bit will be for the sign) (附加位将用于符号)

In multiplication, I've first expanded the bit-length of each value to avoid overflow.在乘法中,我首先扩展了每个值的位长以避免溢出。 After multiplication, left shift will happen to keep the same fractional part for the output of multiplication.乘法后,左移会发生与乘法的 output 保持相同的小数部分。

In addition, I've added saturation for the output, in order to avoid any overflow (if overflow happens, then output will keep the maximum absolute value that it can keep irrespective of the sign)此外,我为 output 添加了饱和度,以避免任何溢出(如果发生溢出,则 output 将保持它可以保持的最大绝对值,而与符号无关)

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM