Подтвердить что ты не робот

Отображение числового диапазона на другой

Математика никогда не была моим сильным костюмом в школе: (

int input_start = 0; // The lowest number of the range input.
int input_end = 254; // The lowest number of the range input.
int output_start = 500; // The lowest number of the range output.
int output_end = 5500; // The largest number of the range ouput.

int input = 127; // Input value.
int output = 0;

Как преобразовать входное значение в соответствующее выходное значение этого диапазона?

Например, входное значение "0" будет равным выходному значению "500", входное значение "254" будет равно выходному значению "5500". Я не могу понять, как вычислить выходное значение, если входное значение имеет значение 50 или 101.

Я уверен, что это просто, я не могу сейчас думать:)

Изменить: мне просто нужны целые числа, никакие доли или что-то еще.

4b9b3361

Ответ 1

Забудьте о математике и попытайтесь решить эту проблему интуитивно.

Во-первых, если мы хотим отобразить номера ввода в диапазоне [ 0, x] для вывода диапазона [0, y], нам просто нужно масштабировать соответствующую сумму. 0 переходит в 0, x переходит в y, а число t переходит в (y/x)*t.

Итак, позвольте мне свести вашу проблему к вышеуказанной более простой проблеме.

Входной диапазон [ input_start, input_end] имеет input_end - input_start + 1 номера. Таким образом, это эквивалентно диапазону [0, r], где r = input_end - input_start.

Аналогично, выходной диапазон эквивалентен [ 0, r], где R = output_end - output_start.

Ввод input эквивалентен x = input - input_start. Это, начиная с первого абзаца, будет переведено на y = (R/r)*x. Затем мы можем перевести значение y обратно в исходный выходной диапазон, добавив output_start: output = output_start + y.

Это дает нам:

output = output_start + ((output_end - output_start) / (input_end - input_start)) * (input - input_start)

Или, иначе:

/* Note, "slope" below is a constant for given numbers, so if you are calculating
   a lot of output values, it makes sense to calculate it once.  It also makes
   understanding the code easier */
slope = (output_end - output_start) / (input_end - input_start)
output = output_start + slope * (input - input_start)

Теперь, когда это C и деление на C усекает, вы должны попытаться получить более точный ответ, вычислив вещи в плавающей точке:

double slope = 1.0 * (output_end - output_start) / (input_end - input_start)
output = output_start + slope * (input - input_start)

Если бы вы хотели быть более корректным, вы бы сделали округление вместо усечения на последнем шаге. Вы можете сделать это, написав простую функцию round:

#include <math.h>
double round(double d)
{
    return floor(d + 0.5);
}

Тогда:

output = output_start + round(slope * (input - input_start))

Ответ 2

Arduino имеет встроенный модуль map.

Пример:

/* Map an analog value to 8 bits (0 to 255) */
void setup() {}

void loop()
{
  int val = analogRead(0);
  val = map(val, 0, 1023, 0, 255);
  analogWrite(9, val);
}

Он также имеет реализацию на этой странице:

long map(long x, long in_min, long in_max, long out_min, long out_max)
{
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

Ответ 3

Решающим моментом здесь является целочисленное деление (которое включает округление) в нужном месте. Ни один из ответов до сих пор не получил правильных круглых скобок. Вот правильный путь:

int input_range = input_end - input_start;
int output_range = output_end - output_start;

output = (input - input_start)*output_range / input_range + output_start;

Ответ 4

формула

f (x) = (x - input_start)/(input_end - input_start) * (output_end - output_start) + output_start

Я подключу этот пост здесь: https://betterexplained.com/articles/rethinking-arithmetic-a-visual-guide/, поскольку он очень помог мне, пытаясь придумать это интуитивно. Как только вы поймете, что говорит пост, тривиально придумать эти формулы самостоятельно. Заметьте, что я тоже занимался такими вопросами. (У меня нет веток - я просто нашел это очень полезным)

скажем, у вас есть диапазон [input_start..input_end], пусть начнется с нормализации его так, что 0 - input_start, а 1 - input_end. это простой способ облегчить задачу.

Как мы это делаем? мы должны будем сдвинуть все, оставшееся на величину input_start, так что если вход x будет input_start, он должен дать нуль.

так что пусть f(x) - это функция, которая выполняет преобразование.

f(x) = x - input_start

пусть попробует:

f(input_start) = input_start - input_start = 0

работает для input_start.

на данный момент он еще не работает для input_end, так как мы не масштабировали его.

пусть просто уменьшит его на длину диапазона, тогда мы получим самое большое значение (input_end), сопоставленное одному.

f(x) = (x - input_start) / (input_end - input_start)

хорошо, давайте попробуем с input_end.

f (input_end) = (input_end - input_start)/(input_end - input_start) = 1

удивительный, кажется, работает.

хорошо, следующий шаг, мы на самом деле масштабируем его до диапазона вывода. Это так же тривиально, как просто умножение на фактическую длину выходного диапазона, как таковое:

f(x) = (x - input_start) / (input_end - input_start) * (output_end - output_start)

теперь, фактически, мы почти закончили, нам просто нужно сдвинуть его вправо, чтобы 0 начиналось с output_start.

f(x) = (x - input_start) / (input_end - input_start) * (output_end - output_start) + output_start

пусть быстро попробует.

f(input_start) = (input_start - input_start) / (input_end - input_start) * (output_end - output_start) + output_start

вы видите, что первая часть уравнения в значительной степени умножается на ноль, тем самым отменяя все, предоставляя вам

f(input_start) = output_start

попробуйте также input_end.

f(input_end) = (input_end - input_start) / (input_end - input_start) * (output_end - output_start) + output_start

который, в свою очередь, будет следующим:

f(input_end) = output_end - output_start + output_start = output_end

как вы можете видеть, теперь это выглядит правильно.

Ответ 5

output = ((input - input_start)/(input_end - input_start)) * (output_end - output_start) + output_start

Что это значит, так это выяснить "насколько далеко" входной диапазон ввода. Затем он применяет эту пропорцию к размеру выходного диапазона, чтобы в абсолютном выражении узнать, насколько далеко должен быть выходной выход. Затем он добавляет начало выходного диапазона для получения фактического номера выхода.