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

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

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.

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

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

Давайте забудем математику и попытаемся решить эту задачу интуитивно.

Во-первых, если мы хотим отображать номера ввода в диапазоне [ 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  double round(double d) { return floor(d + 0.5); } 

Затем:

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

Arduino имеет встроенную карту .

Пример:

 /* 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; } 

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

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

формула

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 

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

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

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

  • Сериализация нескольких свойств DateTime в одном classе с использованием разных форматов для каждого из них
  • C # эквивалент DllMain в C (WinAPI)
  • Как я могу получить метод расширения для изменения исходного объекта?
  • мультимножество, карта и hash-карта сложности
  • Является результатом printf ("% d% d", c ++, c); также не определено?
  • Получить URL-адрес Firefox?
  • Код C ++ для проверки гипотезы Collatz быстрее, чем assembly вручную - почему?
  • Не удалось найти часть пути ... bin \ roslyn \ csc.exe
  • HashSet, который сохраняет порядок
  • Как хранятся 3D-массивы в C?
  • Массивные срезы в C #
  • Interesting Posts

    Как реализовать getfilter () с пользовательским адаптером, который расширяет базовый адаптер

    Как Eclipse компилирует classы только с JRE?

    Ноутбук Toshiba A200 под управлением Ubuntu зависает / зависает при подключении

    Изменить цвет панели инструментов в Appcompat 21

    Android Studio: «Использовать оболочку gradleиента по умолчанию» против «Использовать настраиваемую оболочку gradleиента»

    Причина «Журнала контекстного ядра сеанса» не удалось запустить ошибку в журнале событий?

    Как открыть одну конкретную папку из галереи в android?

    Является ли хорошей практикой освобождение NULL-указателя в C?

    Как избежать исключения «Circular view path» с использованием теста Spring MVC

    Насколько надежны 2,5 "внешние жесткие диски?

    неожиданный результат GetType () для записи объекта

    Как использовать цикл for и вывод в другой каталог

    Отображение динамического изображения из базы данных с помощью p: graphicImage и StreamedContent

    Обновление и установка пакетов через командную строку Cygwin?

    Ассоциация «Много ко многим» MongoDB

    Давайте будем гением компьютера.