然而,我正在使用没有浮点精度空间的微芯片。我需要考虑一些方程式中的小数值。到目前为止,我已经运气好了使用旧的* 100 - > / 100方法如下:
increment = (short int)(((value1 - value2)*100 / totalSteps));
// later in the code I loop through the number of totolSteps
// adding back the increment to arrive at the total I want at the precise time
// time I need it.
newValue = oldValue + (increment / 100);
这适用于0-255之间的值除以最多300的totalSteps。在300之后,小数点右边的小数值变得很重要,因为它们会随着时间的推移而累加。
我很好奇是否有人有更好的方法在整数范式内保存小数精度?我尝试使用* 1000/1000,但这根本不起作用。
提前谢谢你。
答案 0 :(得分:2)
带整数的分数称为定点数学。
尝试谷歌搜索“固定点”。
固定点提示和技巧超出了SO答案的范围......
示例:5点击FIR滤波器
// C是使用2.8固定精度的滤波器系数。 // 2 MSB(10)是整数部分,8 LSB(10)是分数部分。 //这里的实际分数精度是1/256。
int FIR_5(int* in, // input samples
int inPrec, // sample fraction precision
int* c, // filter coefficients
int cPrec) // coefficients fraction precision
{
const int coefHalf = (cPrec > 0) ? 1 << (cPrec - 1) : 0; // value of 0.5 using cPrec
int sum = 0;
for ( int i = 0; i < 5; ++i )
{
sum += in[i] * c[i];
}
// sum's precision is X.N. where N = inPrec + cPrec;
// return to original precision (inPrec)
sum = (sum + coefHalf) >> cPrec; // adding coefHalf for rounding
return sum;
}
int main()
{
const int filterPrec = 8;
int C[5] = { 8, 16, 208, 16, 8 }; // 1.0 == 256 in 2.8 fixed point. Filter value are 8/256, 16/256, 208/256, etc.
int W[5] = { 10, 203, 40, 50, 72}; // A sampling window (example)
int res = FIR_5(W, 0, C, filterPrec);
return 0;
}
备注:强>
在上面的例子中:
1
的每个变化都被视为1/256。 1 << 8 == 256
。half
以降低错误。half
,其为128(1 <&lt; 7)。所以A =(A + 128)>&gt; 8 - &gt; 1。答案 1 :(得分:1)
不要使用这种方法。
新范例:不要使用FP数学或定点数学累积。使用整数数学进行累积和其他方程式。任何时候你需要获得一些缩放值,除以你的比例因子(100),但用原始的,未缩放的值做“加起来”部分。
答案 2 :(得分:1)
如果您真的无法在每一步直接插值,那么可以快速尝试插值的精确理性(Bresenham-esque)版本。
div_t frac_step = div(target - source, num_steps);
if(frac_step.rem < 0) {
// Annoying special case to deal with rounding towards zero.
// Alternatively check for the error term slipping to < -num_steps as well
frac_step.rem = -frac_step.rem;
--frac_step.quot;
}
unsigned int error = 0;
do {
// Add the integer term plus an accumulated fraction
error += frac_step.rem;
if(error >= num_steps) {
// Time to carry
error -= num_steps;
++source;
}
source += frac_step.quot;
} while(--num_steps);
与定点解决方案相比,一个主要缺点是,如果您使用该函数以不同的步长连续走向移动目标,则小数项在迭代之间得到舍入。
哦,为了记录,您的原始代码似乎没有在步进时正确累积分数,例如无论步数采取多少次,在加法中总是将1/100增量截断为0。相反,你真的想要将增量添加到更高精度的定点累加器,然后在每次迭代时将其除以100(或者最好是右移以除以2的幂),以便计算整数“位置”。
请注意计算中所需的不同整数类型和范围。乘以1000将溢出16位整数,除非一个项是long。完成计算并跟踪每一步的输入范围和余量,然后选择要匹配的整数类型。
答案 3 :(得分:0)
也许你可以通过保存来模拟浮点行为 它使用IEEE 754规范
因此,您将mantisse,exponent和sign保存为unsigned int值。
对于计算,您使用然后按位添加mantisse和exponent等等。 乘法和除法可以通过按位加法运算替换。
我认为很多编程人员都会模仿,但它应该有用。
答案 4 :(得分:0)
您选择的类型是问题:short int
可能是16位宽。这就是为什么大型乘法器不起作用的原因 - 你被限制在+/- 32767。假设您的编译器支持它,请使用32位long int
。顺便说一下,它是什么芯片,以及什么编译器?