-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 で、float で 4294967295 になると予想しています。

もっとうまくやるアイデアはありますか?基本的な考え方は、値を範囲から別の範囲に変換して、異なるデータ型の可能性を持たせることです。

4

2 に答える 2

0

romkyns の回答に追加すると、オーバーフローを防ぐためにキャストする前にすべての値を double にキャストするだけでなく、値を適切に調整しないため、下限が 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] にマッピングすると、次の結果が得られます。

  • convertRatio(-1.0, -1.0, 1.0, 3.0, 2.0) = 3.0
  • convertRatio(-0.8, -1.0, 1.0, 3.0, 2.0) = 2.9
  • convertRatio(0.8, -1.0, 1.0, 3.0, 2.0) = 2.1
  • convertRatio(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 に答える
0

試す

(double) inpMaxLevel - (double) inpMinLevel

代わりは。現在行っていることは、数値がまだ int 型である間にmin から max を減算することです。これは必然的にオーバーフローします。signed int は、その最小値と最大値の差を基本的に表すことができません。

于 2010-08-02T11:57:40.350 に答える