【问题标题】:Float to fixed conversion浮动到固定转换
【发布时间】:2015-02-12 17:13:13
【问题描述】:

这是一个基本问题,但我很困惑。

我有一个格式为 1.4.12 的寄存器。这意味着它需要一个浮点数并取范围 -15.9999 - 15.9999,这是正确的,还是有多少个 9?我对范围感到困惑。

我需要将 c++ 浮点数转换为定点数并将其放入寄存器中吗?在 C 中是否有任何 std:: 库可以做到这一点?如果没有,是否有任何人可以指出我的标准代码?

另外,如何将固定转换为浮动会很好?

【问题讨论】:

  • 你在说什么“注册”? CPU 寄存器通常不会那样工作。
  • 什么“注册”?你如何从那种“格式”中得到这些数字?到目前为止,您尝试过什么?
  • 硬件在什么上注册?
  • 二进制数不使用九作为限制。是一个二进制数。所以 .9999 是 9999/10000,在你的情况下它是 4095/4096。
  • 我真的必须为你拼出来吗?范围是 +/- (15 + 4095/4096)。那是 -15.999755859375 到 15.999755859375。

标签: c++ math floating-point fixed-point


【解决方案1】:

自己做这件事很简单:

typedef int32_t fixed;

fixed float_to_fixed(float x)
{
    return (fixed)(x * 65536.0f / 16.0f);
}

请注意,这没有范围检查,因此如果 x 可能超出您的定点类型的有效范围,那么您可能需要添加一些检查并根据需要饱和或抛出错误。

同样用于另一个方向的转换:

float fixed_to_float(fixed x)
{
    return (float)x * 16.0f / 65536.0f;
}

(这个当然不需要任何范围检查。)

【讨论】:

  • 非常感谢。我猜这是最大16位。但就我而言,我有 17 个。我只需要使用 32.0f 和 2147483647 吗?有什么链接或提示可以知道范围吗?
  • 确定你有17位吗?我以为那是一个错字。不过,将上面的代码调整为您需要的任何定点格式都非常容易。如果它确实是 17 位,那么您需要指定使用什么大小的字(24 位?32 位?)以及 17 位在字中的位置(例如 MS 或 LS)。
  • 我现在更新了答案以使用 32 位字长,并将 17 个定点位放在这个 32 位字的最低有效 17 位中。
  • 是的,有些是 17,有些是 18 和 22 等等……每个硬件寄存器的长度是 32 位。我放置它们的位置取决于寄存器,它可以是位 0:16 和其他位 5:21。有很多变化。一个字是32位。
  • 好的 - 上面的例子应该足以让你开始 - 将位转移到 32 位字中的所需位置当然很容易。
【解决方案2】:

如果你需要使用定点,那么你必须实现加法和乘法运算。在这种情况下,您需要担心为小数部分分配了多少位以及为整数部分分配了多少位。然后您可以根据自己的喜好进行“移位”操作。

在以下代码-sn-p 中,我通过为小数部分分配 22 位和为整数部分分配 9 位来实现定点。 (附加位将用于符号)

在乘法中,我首先扩展了每个值的位长以避免溢出。乘法后,左移会发生乘法输出保持相同的小数部分。

此外,我为输出添加了饱和度,以避免任何溢出(如果发生溢出,则输出将保持它可以保持的最大绝对值与符号无关)

#include <stdio.h>
#include <math.h>
#include <stdint.h>

#define fractional_bits 22
#define fixed_type_bits 32

typedef int32_t fixed_type;
typedef int64_t expand_type;

fixed_type float_to_fixed(float inp)
{
    return (fixed_type)(inp * (1 << fractional_bits));
}

float fixed_to_float(fixed_type inp)
{
    return ((float)inp) / (1 << fractional_bits);
}

fixed_type fixed_mult(fixed_type inp_1, fixed_type inp_2)
{
    return (fixed_type)(((expand_type)inp_1 * (expand_type)inp_2) >> fractional_bits);
}

fixed_type fixed_add(fixed_type inp_1, fixed_type inp_2)
{
    fixed_type inp_1_sign = inp_1 >> (fixed_type_bits - 1);
    fixed_type inp_2_sign = inp_2 >> (fixed_type_bits - 1);
    fixed_type add = inp_1 + inp_2;
    fixed_type add_sign = add >> (fixed_type_bits - 1);

    if (inp_1_sign != inp_2_sign)
    {
        return add;
    }
    else if (add_sign == inp_1_sign)
    {
        return add;
    }
    else if (add_sign == -1)
    {
        return ((1 << (fixed_type_bits - 2)) - 1 + (1 << (fixed_type_bits - 2)));
    }
    else if (add_sign == 1)
    {
        return (1 << (fixed_type_bits - 1));
    }
}

【讨论】:

    猜你喜欢
    • 2011-02-04
    • 1970-01-01
    • 2012-04-04
    • 2023-04-01
    • 1970-01-01
    • 2017-04-20
    • 2023-03-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多