Converting floating point to fixed point

后端 未结 6 1827
耶瑟儿~
耶瑟儿~ 2020-12-23 12:13

In C++, what\'s the generic way to convert any floating point value (float) to fixed point (int, 16:16 or 24:8)?

EDIT: For clarification, fixed-poin

相关标签:
6条回答
  • 2020-12-23 12:52

    I gave the answer to the guy that wrote the best answer, but I really used a related questions code that points here.

    It used templates and was easy to ditch dependencies on the boost lib.

    0 讨论(0)
  • 2020-12-23 12:55

    **** Edit** : My first comment applies to before Kevin's edit,but I'll leave it here for posterity. Answers change so quickly here sometimes!

    The problem with Kevin's approach is that with Fixed Point you are normally packing into a guaranteed word size (typically 32bits). Declaring the two parts separately leaves you to the whim of your compiler's structure packing. Yes you could force it, but it does not work for anything other than 16:16 representation.

    KPexEA is closer to the mark by packing everything into int - although I would use "signed long" to try and be explicit on 32bits. Then you can use his approach for generating the fixed point value, and bit slicing do extract the component parts again. His suggestion also covers the 24:8 case.

    ( And everyone else who suggested just static_cast.....what were you thinking? ;) )

    0 讨论(0)
  • 2020-12-23 12:57

    A cast from float to integer will throw away the fractional portion so if you want to keep that fraction around as fixed point then you just multiply the float before casting it. The below code will not check for overflow mind you.

    If you want 16:16

    double f = 1.2345;
    int n;
    
    n=(int)(f*65536);
    

    if you want 24:8

    double f = 1.2345;
    int n;
    
    n=(int)(f*256);
    
    0 讨论(0)
  • 2020-12-23 13:09

    This is fine for converting from floating point to integer, but the O.P. also wanted fixed point.

    Now how you'd do that in C++, I don't know (C++ not being something I can think in readily). Perhaps try a scaled-integer approach, i.e. use a 32 or 64 bit integer and programmatically allocate the last, say, 6 digits to what's on the right hand side of the decimal point.

    0 讨论(0)
  • 2020-12-23 13:11

    Here you go:

    // A signed fixed-point 16:16 class
    class FixedPoint_16_16
    {
        short          intPart;
        unsigned short fracPart;
    
    public:
        FixedPoint_16_16(double d)
        {
            *this = d; // calls operator=
        }
    
        FixedPoint_16_16& operator=(double d)
        {
            intPart = static_cast<short>(d);
            fracPart = static_cast<unsigned short>
                        (numeric_limits<unsigned short> + 1.0)*d);
            return *this;
        }
    
        // Other operators can be defined here
    };
    

    EDIT: Here's a more general class based on anothercommon way to deal with fixed-point numbers (and which KPexEA pointed out):

    template <class BaseType, size_t FracDigits>
    class fixed_point
    {
        const static BaseType factor = 1 << FracDigits;
    
        BaseType data;
    
    public:
        fixed_point(double d)
        {
            *this = d; // calls operator=
        }
    
        fixed_point& operator=(double d)
        {
            data = static_cast<BaseType>(d*factor);
            return *this;
        }
    
        BaseType raw_data() const
        {
            return data;
        }
    
        // Other operators can be defined here
    };
    
    
    fixed_point<int, 8> fp1;           // Will be signed 24:8 (if int is 32-bits)
    fixed_point<unsigned int, 16> fp1; // Will be unsigned 16:16 (if int is 32-bits)
    
    0 讨论(0)
  • 2020-12-23 13:12

    There isn't any built in support in C++ for fixed point numbers. Your best bet would be to write a wrapper 'FixedInt' class that takes doubles and converts them.

    As for a generic method to convert... the int part is easy enough, just grab the integer part of the value and store it in the upper bits... decimal part would be something along the lines of:

    for (int i = 1; i <= precision; i++)
    {
       if (decimal_part > 1.f/(float)(i + 1)
       {
          decimal_part -= 1.f/(float)(i + 1);
          fixint_value |= (1 << precision - i);
       }
    }
    

    although this is likely to contain bugs still

    0 讨论(0)
提交回复
热议问题