-1

我有以下代码:

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。

你有什么想法可以做得更好吗?基本思想只是将一个范围内的值转换为具有不同数据类型可能性的另一个范围。

4

2 回答 2

0

尝试

(double) inpMaxLevel - (double) inpMinLevel

反而。您目前正在做的是从 min 中减去 max而数字仍然是 int 类型- 这必然会溢出;有符号的 int 从根本上无法表示其最小值和最大值之间的差异。

于 2010-08-02T11:57:40.350 回答
0

添加到 romkyns 答案中,除了在转换之前将所有值转换为双精度值以防止溢出之外,当下限不同于 0 时,您的代码会返回错误结果,因为您没有适当地调整值。这个想法是将范围 [in_min, in_max] 映射到范围 [out_min, out_max],所以:

  • f(in_min) = out_min
  • f(in_max) = out_max

令 x 为要映射的值。该算法类似于:

  • 将范围 [in_min, in_max] 映射到 [0, in_max - in_min]。为此,请从 x 中减去 in_min。
  • 将范围 [0, in_max - in_min] 映射到 [0, 1]。为此,将 x 除以 (in_max - in_min)。
  • 将范围 [0, 1] 映射到 [0, out_max - out_min]。为此,请将 x 乘以 (out_max - out_min)。
  • 将范围 [0, out_max - out_min] 映射到 [out_min, out_max]。为此,请将 out_min 添加到 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],得到以下结果:

  • 转换比率(-1.0, -1.0, 1.0, 3.0, 2.0) = 3.0
  • 转换比率(-0.8, -1.0, 1.0, 3.0, 2.0) = 2.9
  • 转换比率(0.8, -1.0, 1.0, 3.0, 2.0) = 2.1
  • 转换比率(1.0, -1.0, 1.0, 3.0, 2.0) = 2.0

唯一需要的条件是 in_min != in_max (防止被零除)和 out_min != out_max (否则,所有输入将映射到同一点)。为防止舍入错误,请尽量不要使用小范围。

于 2010-08-03T06:49:17.170 回答