我在我的一些程序中使用了这两种插值方法......
__forceinline double InterpolateDouble(double dOldVal, double dOldMin, double dOldMax, double dNewMin, double dNewMax)
{
return (((dOldVal - dOldMin) * (dNewMax - dNewMin)) / (dOldMax - dOldMin)) + dNewMin;
}
__forceinline int InterpolateInteger(int nOldVal, int nOldMin, int nOldMax, int nNewMin, int nNewMax)
{
return (int)InterpolateDouble((double)nOldVal, (double)nOldMin, (double)nOldMax, (double)nNewMin, (double)nNewMax);
}
方法InterpolateInteger()
只是调用InterpolateDouble()
方法来保持一些小数精度。从整数到双精度的转换是一个问题,有没有办法只使用整数(没有转换)获得准确的结果?
答案 0 :(得分:0)
在分割前乘法时存在溢出的风险,正如您的代码在此处所做的那样。除了代码中可能的乘法中间计算之外,还必须检查输入的可能值,以确定int类型是否总是足以包含计算。截断将以整数除法发生,但如果你想要一个整数结果,那就是预期的。 从CPU的角度来看,从int到double的转换是微不足道的,因为在计算之前在整数的前面有一个0。
答案 1 :(得分:0)
这不是你应该担心的从int到double的转换。这是工作完成后从double到int的转换(截断)。考虑将[0,500]插值为[0,1]。在这种情况下,一旦你进行插值加倍,对于500输入,数字将是1输出,对于输入0-499,数字将小于1。因此,截断后0-499输入将导致0输出,500将导致1。
答案 2 :(得分:0)
如果您在最大优化之后并且插值点已修复,则可以使用以下整数表达式:
(dOldVal * dNewDelta + dNewMin * dOldDelta - dOldMin * dNewDelta) / dOldDelta
格式为(A * X + B) / C
,其中A
,B
和C
是三个预先计算的整数常量。这将产生精确的整数答案。
或者,使用具有双精度预计算系数的A * X + B
,但需要仔细调整舍入策略。
另一种可能性是使用2的幂重新缩放和舍入A
和B
系数,给出形式的快速除法整数公式
(A * X + B) >> p
(舍入策略也很微妙)。