模拟定点除法/乘法

问题描述 投票:0回答:3

我正在编写一个定点类,但遇到了一些障碍......乘法、除法部分,我不知道如何模拟。我对部门操作员进行了非常粗暴的批评,但我确信这是错误的。这是到目前为止的样子:

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

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

该类的

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

我不想问,但如果有人知道我在哪里可以找到类似的文档,甚至只是“技巧”或如何执行这两个操作符,我会非常高兴!当谈到数学时,我是个傻瓜,我知道以前有人必须这样做/问过这个问题,但搜索谷歌一次并没有把我带到应许之地......

c++ bit-manipulation multiplication fixed-point integer-division
3个回答
3
投票

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

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

我对除法有点生疏——在 DSP 中,我在那里学习了这些东西,我们尽可能避免(昂贵的)除法!


0
投票

要启动并运行,首先实现(一元)

inverse(x) = 1/x
,然后将
a/b
实现为
a*inverse(b)
。您可能希望将中间体表示为 32.32 格式。


0
投票

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

  • 乘法:

     operator*(const Fixed &other) const {
         return Fixed(((int64_t)value * (int64_t)other.value) >> 16);
     }
    

    1 表示为 1 << 16, so you need to divide by 1 << 16 at the end to compensate.

  • 部门:

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

    1 表示为 1 << 16, so you need to multiply by 1 << 16 before to compensate.

64 位整数是

  • 在 gcc 上,
    stdint.h
    (或
    cstdint
    ,将它们放置在
    std::
    命名空间中)应该可用,因此您可以使用我上面提到的类型。否则,在 32 位目标上为
    long long
    ,在 64 位目标上为
    long
  • 在 Windows 上,始终为
    long long
    __int64
© www.soinside.com 2019 - 2024. All rights reserved.