преобразователь произвольного типа данных - PullRequest
0 голосов
/ 02 августа 2010

У меня есть следующий код:

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 в плавающей запятой.

Есть ли у вас идеи сделать это лучше? Основная идея - просто преобразовать значение из диапазона в другой диапазон с возможностью другого типа данных.

Ответы [ 2 ]

0 голосов
/ 03 августа 2010

Добавление ответа 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]. Для этого вычтите in_min из x.
  • Отображение диапазона [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
  • 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 (в противном случае все входы будут отображаться в одну точку). Чтобы избежать ошибок округления, старайтесь не использовать маленькие диапазоны.

0 голосов
/ 02 августа 2010

Попробуйте

(double) inpMaxLevel - (double) inpMinLevel

.В настоящее время вы вычитаете max из min , в то время как числа по-прежнему имеют тип int - который обязательно переполняется;подписанное int принципиально неспособно представить разницу между его минимальным и максимальным значениями.

...