任意数据类型比率转换器
我有以下代码:
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。
你有什么想法可以做得更好吗? 基本思想是将值从一个范围转换为另一个具有不同数据类型可能性的范围。
I have following code:
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);
}
the usage is something like this:
int value = convertRatio<float,int,-1.0f,1.0f>(0.5);
//value is around 1073741823 ( a quarter range of signed int)
the problem is for I=int
and O=float
with function default parameter:
float value = convertRatio<int,float>(123456);
the line double(inpMaxLevel - inpMinLevel)
result is -1.0, and I expect it to be 4294967295 in float.
do you have any idea to do it better?
the base idea is just to convert a value from a range to another range with posibility of different data type.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
添加到 romkyns 答案中,除了在转换之前将所有值转换为双精度数以防止溢出之外,当下限不同于 0 时,您的代码会返回错误的结果,因为您没有适当地调整值。这个想法是将范围 [in_min, in_max] 映射到范围 [out_min, out_max],因此:
令 x 为要映射的值。该算法类似于:
下面的 C++ 实现就是这样做的(我会忘记默认值以使代码更清晰:
请注意,我没有采用范围大小的绝对值。这允许反向映射。例如,它可以映射 [- 1.0, 1.0] 到 [3.0, 2.0],得到以下结果:
唯一需要的条件是 in_min != in_max (防止被零除)和 out_min != out_max (否则,所有输入将映射到同一点)。为防止舍入错误,请尽量不要使用小范围。
Adding to romkyns answer, besides casting all values to doubles before casting to prevent overflows, your code returns wrong results when the lower bounds are distinct than 0, because you don't adjust the values appropiately. The idea is mapping the range [in_min, in_max] to the range [out_min, out_max], so:
Let x be the value to map. The algorithm is something like:
The following implementation in C++ does this (I will forget the default values to make the code clearer:
Notice that I didn't took the absolute value of the range sizes. This allows reverse mapping. For example, it makes possible to map [-1.0, 1.0] to [3.0, 2.0], giving the following results:
The only condition needed is that in_min != in_max (to prevent division by zero) and out_min != out_max (otherwise, all inputs will be mapped to the same point). To prevent rounding errors, try to not use small ranges.
尝试
一下。您当前正在做的事情是从 min 中减去 max ,而数字仍然是 int 类型 - 这必然会溢出;有符号 int 根本上无法表示其最小值和最大值之间的差异。
Try
instead. What you are doing currently is subtracting max from min while the numbers are still of type int - which necessarily overflows; a signed int is fundamentally incapable of representing the difference between its min and max.