Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 任意数据类型比率转换器_C++_Templates_Math_Numeric - Fatal编程技术网

C++ 任意数据类型比率转换器

C++ 任意数据类型比率转换器,c++,templates,math,numeric,C++,Templates,Math,Numeric,我有以下代码: 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 out

我有以下代码:

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);
}
double(inpMaxLevel-inpMinLevel)
的结果是-1.0,我希望它在float中是4294967295

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

试试看

(double) inpMaxLevel - (double) inpMinLevel

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

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

  • f(输入最小)=输出最小
  • 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\u max-out\u min]。为此,将x乘以(out_max-out_min)
  • 将范围[0,out\u max-out\u min]映射到[out\u min,out\u max]。要执行此操作,请将_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);
}
模板
O转换比(I x,I in_min,I in_max,O out_min,O out_max){
常数双t=((双)x-(双)英寸)/
((双)英寸最大值-(双)英寸最小值);
常数双精度=t*((双精度)输出最大值-(双精度)输出最小值)+输出最小值;
返回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(否则,所有输入将映射到同一点)。为了防止舍入错误,请尽量不要使用小范围。

@uray-仔细观察,不会发生溢出,因为据我所知,没有其他数值类型可以溢出双精度。至于舍入错误-我不确定,对不起。如果我没有弄错的话
数值限制::min()
数值限制::min()
有一个完全不同的含义:对于浮点,它是最小的正非零值。我不知道如何将这两个值混合起来,得到有意义的值。是的,如果t是浮点,那么用户应该超出默认值
(double) inpMaxLevel - (double) inpMinLevel
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);
}