我有以下代码:
template<typename I,typename O> O convertRatio(I input,
I inpMinLevel = std::numeric_limits<I>::min(),
I inpMaxLevel = std::numeric_limits<I>::max(),
O outMinLevel = std::numeric_limits<O>::min(),
O outMaxLevel = std::numeric_limits<O>::max() )
{
double inpRange = abs(double(inpMaxLevel - inpMinLevel));
double outRange = abs(double(outMaxLevel - outMinLevel));
double level = double(input)/inpRange;
return O(outRange*level);
}
用法是这样的:
int value = convertRatio<float,int,-1.0f,1.0f>(0.5);
//value is around 1073741823 ( a quarter range of signed int)
问题出在I=int
和O=float
的函数默认参数:
float value = convertRatio<int,float>(123456);
行double(inpMaxLevel - inpMinLevel)
结果为-1.0,我希望它在浮动中为4294967295。
你有什么想法做得更好吗? 基本思想就是将一个值从一个范围转换为另一个范围,并且具有不同数据类型的可能性。
答案 0 :(得分:0)
尝试
(double) inpMaxLevel - (double) inpMinLevel
代替。你当前正在做的是从min 中减去max,而数字仍然是int - 这必然会溢出;有符号的int基本上无法表示其最小值和最大值之间的差异。
答案 1 :(得分:0)
添加到romkyns的答案,除了在转换之前将所有值转换为双精度以防止溢出之外,当下限不同于0时,代码会返回错误的结果,因为您没有适当地调整值。想法是将范围[in_min,in_max]映射到范围[out_min,out_max],所以:
设x为要映射的值。该算法类似于:
C ++中的以下实现做到了这一点(我将忘记默认值以使代码更清晰:
template <class I, class O>
O convertRatio(I x, I in_min, I in_max, O out_min, O out_max) {
const double t = ((double)x - (double)in_min) /
((double)in_max - (double)in_min);
const double res = t * ((double)out_max - (double)out_min) + out_min;
return O(res);
}
请注意,我没有采用范围大小的绝对值。这允许反向映射。例如,它可以将[-1.0,1.0]映射到[3.0,2.0],得到以下结果:
唯一需要的条件是in_min!= in_max(防止除零)和out_min!= out_max(否则,所有输入都将映射到同一个点)。要防止舍入错误,请尝试不要使用小范围。