使用按位运算(非浮点数)缩放4位数

时间:2014-10-09 20:51:13

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

我想知道如何将浮点变量“增益”值(十进制0.0 - 1.0)乘以一个可变的4位离散值(16个离散级别)以得到一个缩放值,所有这些都是通过NOT使用浮动点数学/数字(最好通过使用逐位运算等)。我正在用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的情况。 0和C> 0但是给出S = 0(即P和C的低值),我将具有设置S = 1(1/15 = 0x01)的条件。这种情况特定于问题。

3 个答案:

答案 0 :(得分:3)

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

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]从来没有使用过,所以你可以在那里优化一点而不利于简单。

您在问题中说您希望使用按位操作。没问题:用+=替换程序中的所有|=

答案 1 :(得分:1)

我认为有两件事要做:首先,将float转换为整数。当然,不是从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种可能性。

答案 2 :(得分:0)

知道了。

使用16位整数值... 其中P = 0x0000:0x000F,C = 0x0000:0x000F(P和C占16个离散电平)

Pscaled =(((P + 1)<< 4)* C)

最后, S = Pscaled>> 8