1

我正在编写一个 Fixedpoint 类,但遇到了一些障碍......乘法,除法部分,我不知道如何模拟。我对除法运算符进行了非常粗暴的抨击,但我确信这是错误的。这是到目前为止的样子:

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

我……不是一个很好的程序员,哈哈!

该类的“部分”是 16 位宽(但表示为一个长的 32 位,因为我想在它们被修复之前它需要空间来容纳可能的溢出),“值”也是如此,它是整数部分。当“部分”在其中一个操作中超过 0xFFFF 时,最高 16 位被添加到“值”中,然后该部分被屏蔽,因此只保留最低 16 位。这是在初始化列表中完成的。

我不想问,但如果有人知道我在哪里可以找到这样的文档,甚至只是“技巧”或如何做这两个运算符,我会很高兴的!在数学方面我是个笨蛋,我知道以前有人必须这样做/问过这个问题,但是搜索谷歌一次并没有把我带到应许之地......

4

3 回答 3

2

正如 Jan 所说,使用单个整数。由于看起来您正在指定 16 位整数和小数部分,因此您可以使用普通的 32 位整数来执行此操作。

“诀窍”是在对数字进行操作时了解数字的“格式”会发生什么。您的格式将被描述为 16.16。当您添加或减去时,格式保持不变。当你乘法时,你会得到 32.32——所以你需要一个 64 位的临时值作为结果。然后你做一个 >>16 的移位来降低到 48.16 格式,然后取底部的 32 位在 16.16 中得到你的答案。

我对划分有点生疏——在 DSP 中,我学到了这些东西,我们尽可能避免(昂贵的)划分!

于 2011-02-17T13:27:01.690 回答
0

我建议使用一个整数值而不是单独的整数和小数部分。加法和减法是直接对应的整数,您可以简单地使用 64 位支持,现在所有常见的编译器都有:

  • 乘法:

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

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

64 位整数是

  • 在 gcc 上,stdint.h(或cstdint将它们放在std::命名空间中)应该可用,因此您可以使用我上面提到的类型。否则它long long在 32 位目标和long64 位目标上。
  • 在 Windows 上,它始终是long long__int64
于 2011-02-17T13:21:12.650 回答
0

要启动并运行,首先实现 (unary) inverse(x) = 1/x,然后实现a/bas a*inverse(b)。您可能希望将中间体表示为 32.32 格式。

于 2011-02-17T14:45:37.520 回答