Как избежать «ловушки» с линейной интерполяцией?

У меня есть диапазон a (начальный диапазон) и диапазон b (целевой диапазон), и мне нужно масштабировать значение aX из диапазона a в диапазоне b, Код — это базовая линейная интерполяция:

double LinearInterpolation(double a0, double a1, double b0, double b1, double aX) {
return b0 + (b1 - b0) * (aX - a0) / (a1 - a0);
}

Дело в том, что диапазон b может иметь длину 0 от 1,0 до 1,0. Но когда я достигаю этого диапазона, я получил значение «ловушка» и не могу вернуться назад. Вот пример:

int main ()
{
double a0 = 0.4;
double a1 = 1.0;
double b0 = 0.6;
double b1 = 1.0;

double aX = 0.58;

aX = LinearInterpolation(a0, a1, b0, b1, aX);
std::cout << aX << std::endl;

b0 = 1.0;
aX = LinearInterpolation(a0, a1, b0, b1, aX);
std::cout << aX << std::endl;

b0 = 0.6;
aX = LinearInterpolation(a0, a1, b0, b1, aX);
std::cout << aX << std::endl;
}

До тех пор b0 0, правильно масштабирует aX значение. Когда я достигну b0 = b1 = 1.0Я не могу вернуться (aX всегда 1,0, потому чтоX = a1так всегда b0 + (b1 - b0) => b1).

Как я могу избежать этого?

1

Решение

Как я могу избежать этого?

Не храните фактическое значение, а относительную позицию в пределах диапазона:

struct value_in_range {
double normalized_offset;
double in_range (double from, double to) const {
return from + (to - from) * normalized_offset;
}
};

value_in_range make_value_in_range (double from, double value, double to) {
// Add assertions to avoid misuse
return {(value - from) / (to - from)};
}

С вашим примером:

int main ()
{
double a0 = 0.4;
double a1 = 1.0;
double b0 = 0.6;
double b1 = 1.0;

double aX = 0.58;

value_in_range X = make_value_in_range (a0, aX, a1);

std::cout << X.in_range(b0, b1) << std::endl;

b0 = 1.0;
std::cout << X.in_range(b0, b1) << std::endl;

b0 = 0.6;
std::cout << X.in_range(b0, b1) << std::endl;
}

Вы также можете установить aX как в вашем оригинальном коде.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]