Как заставить это приложение map() работать по назначению?
Я хочу отобразить диапазон значений 0-63 следующим образом:
x y
0-15 = 0
16-31 = 1
32-47 = 2
48-63 = 3
Однако, используя функцию map y = map(x, 0, 63, 0, 3);
возвращает:
x y
0-15 = 0
16-31 = 0
32-47 = 1
48-63 = 2
Это связано с усечением дробей или с чем-то другим?
Есть ли лучшая альтернатива?
@Erik, 👍1
Обсуждение2 ответа
Лучший ответ:
map()
работает не совсем так, как можно было бы ожидать. Формула такова:
(x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min
И все эти значения являются длинными
, что является "длинным" целым числом. Таким образом, все операции выполняются как целые числа, и это означает, что вы теряете очень большую точность в вычислениях, так как все десятичные компоненты полностью игнорируются.
Это означает, что вы получаете максимальную отдачу только тогда, когда вводите максимальную отдачу.
Как отмечает Майкл Кейзерс, ваш ожидаемый результат равен x/16
(или x>>4
в побитовой нотации), и это может быть достигнуто с помощью map ()
, если вы установите максимальный вход равным 48, а не 63.
Однако простой сдвиг вправо на 4 бита (или деление на 16, если компилятор достаточно умен, чтобы реализовать его как сдвиг вправо) является более эффективным решением, поскольку используемая обработка почти незначительна, тогда как умножение и деление-относительно дорогой набор операций.
Re “_если компилятор достаточно умен, чтобы реализовать его как правый сдвиг”: он сделает это только в том случае, если разделенное не имеет знака, или если он может убедить себя, что оно никогда не может быть отрицательным., @Edgar Bonet
Вы можете попробовать:
y = map(x, 0, 64, 0, 4);
Майенко показал вам формулу, используемую map()
. Вы можете проверить, что
формула работает хорошо,если вы думаете в терминах полуоткрытых интервалов:
[0, 64) → [0, 4)
Но это все равно гораздо менее эффективно, чем сдвиг битов.
- Arduino std::map, возвращающий случайные значения
- Как компенсировать значение смещения джойстиков в нейтральном положении?
- Как свести аналоговый ввод всего к трем случаям?
- Отображение значений с аналогового входа дает неожиданные значения?
- Код для отображения напряжения на датчике и вывода значения в литрах
- Как сопоставить целые значения и округлить их до десятков/тысяч?
- WS2812b - Интерполировать пиксели на неопиксельной матрице с маской
вы можете использовать
y = x / 16
, @Michel Keijzers@MichelKeijzers Отлично, я не думал, что это можно решить так просто! Спасибо за быстрое решение. Несмотря на это, мне все еще любопытна функция map ()..., @Erik