C++: Emulated Fixed Point Division/Multiplication

白昼怎懂夜的黑 提交于 2019-12-07 02:46:24

As Jan says, use a single integer. Since it looks like you're specifying 16 bit integer and fractional parts, you could do this with a plain 32 bit integer.

The "trick" is to realise what happens to the "format" of the number when you do operations on it. Your format would be described as 16.16. When you add or subtract, the format stays the same. When you multiply, you get 32.32 -- So you need a 64 bit temporary value for the result. Then you do a >>16 shift to get down to 48.16 format, then take the bottom 32 bits to get your answer in 16.16.

I'm a little rusty on the division -- In DSP, where I learned this stuff, we avoided (expensive) division wherever possible!

I'd recommend using one integer value instead of separate whole and fractional part. Than addition and subtraction are the integeral counterparts directly and you can simply use 64-bit support, which all common compilers have these days:

  • Multiplication:

    operator*(const Fixed &other) const {
        return Fixed((int64_t)value * (int64_t)other.value);
    }
    
  • Division:

    operator/(const Fixed &other) const {
        return Fixed(((int64_t)value << 16) / (int64_t)other.value);
    }
    

64-bit integers are

  • On gcc, stdint.h (or cstdint, which places them in std:: namespace) should be available, so you can use the types I mentioned above. Otherwise it's long long on 32-bit targets and long on 64-bit targets.
  • On Windows, it's always long long or __int64.

To get things up and running, first implement the (unary) inverse(x) = 1/x, and then implement a/b as a*inverse(b). You'll probably want to represent the intermediates as a 32.32 format.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!