Отображение числового диапазона на другой
Математика никогда не была моим сильным костюмом в школе 🙁
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.
- Почему поля classов не могут быть var?
- Как очистить текст всех текстовых полей в форме?
- Как я могу получить список пользователей из активного каталога?
- Что такое default (object); делать в C #?
- C эквивалентно просмотру fstream
Я уверен, что это просто, я не могу думать прямо сейчас 🙂
Изменить: мне просто нужны целые числа, ни дроби, ни что-нибудь.
- Как проверить, является ли объект допустимым?
- Как читать и писать tags ID3 в MP3 на C #?
- Как исключить свойство из Json Serialization
- Дессериализация данных JSON на C # с использованием JSON.NET
- Как протоколировать сообщения Trace с log4net?
- Создание Qt5 с Visual Studio 2012 / Visual Studio 2013 и интеграция с IDE
- Самый простой способ читать и записывать файлы
- C ++ 11 виртуальных деструкторов и автоматическая генерация специальных функций перемещения
Давайте забудем математику и попытаемся решить эту задачу интуитивно.
Во-первых, если мы хотим отображать номера ввода в диапазоне [ 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
То, что это делает, заключается в том, чтобы выяснить пропорционально «насколько далеко» входной диапазон ввода. Затем он применяет эту пропорцию к размеру выходного диапазона, чтобы в абсолютном выражении узнать, насколько далеко должен быть выходной выход. Затем он добавляет начало выходного диапазона для получения фактического номера выхода.