【问题标题】:Scaling a 4-bit Number Using Bitwise Operations (Not Floating Numbers)使用按位运算(非浮点数)缩放 4 位数
【发布时间】:2014-10-09 20:51:12
【问题描述】:

我想知道如何将一个浮动变量“增益”值(十进制 0.0 - 1.0)乘以一个变量 4 位离散值(16 个离散级别),最终得到一个缩放值,所有这些都通过不使用浮动点数学/数字(最好使用按位运算等)。我正在用 C(XC16 编译器)编写一个 PIC 16 位微控制器来控制一个多色 LED 阵列。每个 LED 可呈现 16 级强度。 P 是该瞬间的原始 LED“图案”强度。 C 是应用于 P 的图案比例值。S 是最终缩放的图案值。

例如,我有一个值 P = 0x0F,我想缩放到其原始值的 50%(即乘以 C = 0.50),最终得到 'S' = 0x08(向上舍入);或 P = 0x00:0x0F 和 C = 0.0:1.0 的任何组合。结果“S”最终应该是一个 4 位数字(16 个离散值,0x00 到 0x0F),但根据“C”缩放原始值的 0-100%。显然,必须采用一些天花板/地板/圆角方法,以及一些类型的铸造。

有什么想法吗?这似乎很容易,但我遇到了麻烦。如果一切都失败了,我可以使用浮点运算来做到这一点。但是,我喜欢使用更有效的方法(并学习一些东西)而不是用浮点数和四舍五入强制它的想法。

*因子“C”可以是任何缩放(或规范化)“P”的东西,至少需要一个仅使用低半字节的短整型(BYTE)类型,分为 16 个级别; 0/15 到 15/15。 'P' 已经是一个 4 位数字,但我想对其应用“增益”以将其从给定值(可能是 0/15 到 15/15)按比例缩小,或者如果增益保持不变值 = 100%。例如,如果 P = 15/15 (0x0F) 且 C = 100%,则 S = 15/15 (0x0F)。现在如果 P = 8/15 (0x07) 且 C = 50%,则 S = 4/15 (0x03)。如果 P = 0,则所有 S = 0。如果 C = 0,则所有 S = 0。对于 P > 0 和 C > 0 但给出 S = 0 的情况(即 P 和 C 的值较低),我将有条件设置 S = 1 (1/15 = 0x01)。这种情况是特定于问题的。

【问题讨论】:

  • 如果C 不是float,则此操作将是微不足道的。比例因子可以是int 吗? C0.0 to 1.0 范围内有大约 1600 万个组合。如果对C 的产生有更多了解,可以进行一些简化。

标签: c floating-point integer bit-manipulation microcontroller


【解决方案1】:

正浮点数随着其表示的位被解释为整数而增加。如果您希望避免浮点运算,您可以在 1/16、2/16、3/16、4/16 表示的位数组中对输入表示的第 th 位进行二进制搜索,……

union u { float f; uint32_t u; } tbl[] = { 0.0f, 0.0625f, 0.125f, … };

int convert_to_4_bits(float f) {
  union u v;
  v.f = f;
  int i;
  /* binary search of v.u in tbl, 
       using 4 32-bit integer comparisons, 
       leaving result in i */
  if (v.u >= tbl[8].u)
    i = 8;
  else
    i = 0;
  if (v.u >= tbl[i+4].u)
    i += 4;
  if (v.u >= tbl[i+2].u)
    i += 2;
  if (v.u >= tbl[i+1].u)
    i += 1;
  return i;
}

我将由您决定边缘情况(即tbl 中的确切值以及是否使用>=> 进行比较。请注意,从未使用过tbl[0],因此您可以优化有点不利于简单性。

您在问题中说您希望使用按位运算。没问题:将程序中的+=全部替换为|=

【讨论】:

    【解决方案2】:

    我认为有两件事要做:首先,将浮点数转换为整数。当然,不是从 0 到 1 的整数(这不会有用),而是从 0 到 2^n 的值,选择 n 以获得最佳精度和速度。考虑到您可能不需要非常精确(从 0 缩放到 15),n=15 肯定就足够了(值从 0 到 32768),因为您可能希望保持在 16 位值内(可能是最佳性能16 位架构),我们可能会走得更低(n=8 -> 0 到 256 可能就足够了,n=12 -> 0..4096 很有趣,因为将它乘以 0..15 值将保持它在 16 位值内)。

    如果您知道您的平台的确切浮点格式,您可以通过提取尾数的高位来做到这一点(有关二进制浮点格式的更多信息,请参阅http://kipirvine.com/asm/workbook/floating_tut.htm)并使用指数按位移动它。

    然后,乘以 0..15 值并除以 n^2(这与按位向下移位 n 相同)。

    如果您不想使用整数乘法并且有几个字节的内存可用,您可以使用某种带有预先计算值的表查找。对于其中一个论点,您只有 0..15 种可能性。

    【讨论】:

      【解决方案3】:

      知道了。

      使用 16 位整数值... 其中 P = 0x0000:0x000F,C = 0x0000:0x000F(P 和 C 具有 16 个离散级别)

      Pscaled = (((P+1)

      最后, S = Pscaled >> 8

      【讨论】:

        猜你喜欢
        • 2017-06-17
        • 2015-05-25
        • 2011-07-17
        • 2022-07-17
        • 1970-01-01
        • 2010-12-15
        • 2011-01-13
        • 2012-06-17
        相关资源
        最近更新 更多