我需要作出数学转换的输入值(线性曲线)到输出值(“对数或指数”曲线)在单片机上有限的资源(内存,时钟速度)。
但是这个问题是比较一般的C程序设计问题。
比如说,我们有两个变量:uint8_t input和uint8_t output。输入值为0-255。输出值也应该是0-255,但与输入不成线性关系。
例如(输入==>输出):
0 ==> 0
1 ==> 1
10 ==> 1
100 ==> 10
200 ==> 75
250 ==> 225
255 ==> 255比方说,我可以做数学转换,比如“2^(输入/32)-1”,我可以实现一些接近我所需要的东西。我试过:
output = (pow(2, (input/32)))-1
但是,根据uint8_t类型变量的局限性,我将得到2: 1,2,4的输出。最多128次(减1次),它们之间没有平稳过渡:
0 ==> 0
1 ==> 0
10 ==> 0
100 ==> 7
200 ==> 63
250 ==> 127
255 ==> 127另外,由于单片机资源有限,我不喜欢使用pow()。我可以通过在内存中使用表实现所需的结果,但是(再次)它将花费256字节的ROM,什么是不可接受的。我也可以用更小的桌子做个近似,但是..。
在低资源单片机的uint8-uint32算法中,可能还有其他的数学方法来实现这一结果吗?
编辑:“正确的”公式和数字不存在。输出数字可能会有所不同。在"input=0“==> "output=0","input=255”==> "output=255“。需求:最小且编译速度最快的代码。预期结果应该接近此图(在uint8_t中):

发布于 2017-05-31 17:49:31
比方说,我可以做数学转换,比如“2^(输入/32)-1”,我可以实现一些接近我所需要的东西。
通过使用余数进行线性插值,您可以得到2^(input/32)的近似。假设input是整数,则可以使用简单的8位计算计算(1 + (input%32)/32.0) * pow(2, input/32)的等效值:
uint8_t f(uint8_t input) {
uint8_t t = (input & 31) + 32;
uint8_t u = input >> 5;
return u < 5 ? t >> (5 - u) : t << (u - 5);
}这将给出两次幂之间的线性插值,如下所示:

更新(数学背景)
我们希望近似函数f(input) = pow(2.0, input/32.0),它只需要整数运算的浮点运算。显而易见的方法是将范围0-255拆分为大小为32的子范围,并在0, 32, 64, 96, 128, 160, 192上使用只能使用整数计算的值,然后对之间的值执行简单的线性插值。现在假设我们要近似一些input的函数值,例如32*u <= input < 32*(u+1),其中u是一个整数。我们知道结尾处的值:f(32*u) = 2^u和f(32*(u+1)) = 2^(u+1)。利用线性插值,我们得到了以下近似:
f_approx(input) = [f(32*(u+1))*(input - 32*u) + f(32*u)*(32*(u+1) - input)]/32现在让我们简化一下:
f_approx(input) = [2^(u+1)*(input - 32*u) + 2^u*(32 - (input - 32*u))]/32
f_approx(input) = 2^u*[2*(input - 32*u) + 32 - (input - 32*u)]/32
f_approx(input) = 2^u*[(input - 32*u) + 32]/2^5
f_approx(input) = [(input - 32*u) + 32]*2^(u-5)现在,如果我们注意到32是2的一个幂,我们可以看到,与input % 32相同的(input - 32*u)也可以计算为input & 31。因此
f_approx(input) = t*2^(u-5)在return中,三元if只是处理u-5的符号,用移位来计算2的幂。
https://stackoverflow.com/questions/44281734
复制相似问题