简体   繁体   English

仿真定点除法/乘法

[英]Emulated Fixed Point Division/Multiplication

I'm writing a Fixedpoint class, but have ran into bit of a snag... The multiplication, division portions, I am not sure how to emulate.我正在写一个定点 class,但遇到了一些麻烦……乘法、除法部分,我不确定如何模拟。 I took a very rough stab at the division operator but I am sure it's wrong.我对部门操作员进行了非常粗暴的尝试,但我确信这是错误的。 Here's what it looks like so far:到目前为止,它是这样的:

class Fixed
{
    Fixed(short int _value, short int _part) : 
        value(long(_value + (_part >> 8))), part(long(_part & 0x0000FFFF)) {};

    ...

    inline Fixed operator -() const  // example of some of the bitwise it's doing
    {
        return Fixed(-value - 1, (~part)&0x0000FFFF);
    };

    ...

    inline Fixed operator / (const Fixed & arg) const // example of how I'm probably doing it wrong
    {
        long int tempInt = value<<8 | part;
        long int tempPart = tempInt;
        tempInt  /= arg.value<<8 | arg.part;
        tempPart %= arg.value<<8 | arg.part;
        return Fixed(tempInt, tempPart);
    };

    long int value, part; // members
};

I... am not a very good programmer, haha!我……不是一个很好的程序员,哈哈!

The class's part is 16 bits wide (but expressed as a 32-bit long since I imagine it'd need the room for possible overflows before they're fixed) and the same goes for value which is the integer part.该类的part是 16 位宽(但表示为 32 位长,因为我想它在修复之前需要为可能的溢出留出空间), value也是如此,即 integer 部分。 When the 'part' goes over 0xFFFF in one of it's operations, the highest 16 bits are added to 'value', and then the part is masked so only it's lowest 16 bits remain.当“部分”在其中一个操作中超过 0xFFFF 时,最高 16 位被添加到“值”,然后该部分被屏蔽,因此只保留它的最低 16 位。 That's done in the init list.这是在初始化列表中完成的。

I hate to ask, but if anyone would know where I could find documentation for something like this, or even just the 'trick' or how to do those two operators, I would be very happy for it, I am a dimwit when it comes to math, and I know someone has had to do/ask this before.我不想问,但如果有人知道我在哪里可以找到这样的文档,甚至只是“技巧”或如何做这两个运算符,我会很高兴,当它来的时候我是个笨蛋数学,我知道以前有人不得不这样做/问这个。 but searching google has for once not taken me to the promised land...但是搜索谷歌一次没有把我带到应许之地......

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.正如 Jan 所说,使用单个 integer。由于看起来您指定的是 16 位 integer 和小数部分,因此您可以使用普通的 32 位 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.您的格式将被描述为 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.当你乘法时,你得到 32.32——所以你需要一个 64 位的临时值作为结果。 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.然后你进行 >>16 移位以得到 48.16 格式,然后取底部 32 位以在 16.16 中得到你的答案。

I'm a little rusty on the division -- In DSP, where I learned this stuff, we avoided (expensive) division wherever possible!我对除法有点生疏——在我学习这些东西的 DSP 中,我们尽可能避免(昂贵的)除法!

I'd recommend using one integer value instead of separate whole and fractional part.我建议使用一个 integer 值,而不是单独的整数部分和小数部分。 Than addition and subtraction are the integeral counterparts directly and you can simply use 64-bit support, which all common compilers have these days:加法和减法直接对应整数,你可以简单地使用 64 位支持,现在所有常见的编译器都有:

  • 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 64 位整数是

  • On gcc, stdint.h (or cstdint , which places them in std:: namespace) should be available, so you can use the types I mentioned above.在 gcc 上, stdint.h (或cstdint ,将它们放在std::命名空间中)应该可用,因此您可以使用我上面提到的类型。 Otherwise it's long long on 32-bit targets and long on 64-bit targets.否则它在 32 位目标上long long long在 64 位目标上很长。
  • On Windows, it's always long long or __int64 .在 Windows 上,它总是long long__int64

To get things up and running, first implement the (unary) inverse(x) = 1/x , and then implement a/b as a*inverse(b) .要启动并运行,首先实现(一元) inverse(x) = 1/x ,然后将a/b实现为a*inverse(b) You'll probably want to represent the intermediates as a 32.32 format.您可能希望将中间体表示为 32.32 格式。

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

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