1

I want to map the value range 0-63 like this:

x       y
0-15  = 0
16-31 = 1
32-47 = 2
48-63 = 3

However, using map function y = map(x, 0, 63, 0, 3); returns:

x       y
0-15  = 0
16-31 = 0
32-47 = 1
48-63 = 2

Is this due to truncating fractions, or something else?

Is there a better alternative?

Erik
  • 271
  • 1
  • 15

2 Answers2

2

map() doesn't quite work as you'd expect. The formula is:

(x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min

And all those values are long, which is a "long" integer. So all operations are done as integers, and that means that you lose an awful lot of precision in the calculation, since all decimal components are completely ignored.

It means that you only get the maximum output when you put in the maximum input.

As Michael Keijzers notes your expected output is x/16 (or x>>4 in bitwise notation), and that can be achieved with map() if you set the maximum input to be 48, not 63.

However a simple right shift 4 bits (or divide by 16 if the compiler is clever enough to implement it as a right shift) is a more efficient solution by far, since the processing involved is almost negligible, whereas multiplying and dividing is a relatively expensive set of operations.

Majenko
  • 105,851
  • 5
  • 82
  • 139
1

You could try:

y = map(x, 0, 64, 0, 4);

Majenko showed you the formula used by map(). You can check that the formula works nicely if you think in terms of half-open intervals:

[0, 64) → [0, 4)

But this is still way less efficient than a bit shift.

Edgar Bonet
  • 45,094
  • 4
  • 42
  • 81