# Unexpected results from map function

I’m trying to use the map function to change values that range from 10000000-15000000 to 0-65535 but I’m getting all kinds of unexpected results. The prototype for that function is

``````long map(long x, long in_min, long in_max, long out_min, long out_max)
``````

so it should be able to handle values that are ~ +/- 2 billion-ish. To test I tried the following code

``````for(long a = 5000000; a < 10000000; a += 500000) {
Serial.println("a: " + String(a) + " -> " + String(map(a, 5000000, 10000000, 0, 65535)));
delay(500);
}
``````

and got this as output

``````a: 5000000 -> 0
a: 5500000 -> -318
a: 6000000 -> 222
a: 6500000 -> -96
a: 7000000 -> -414
a: 7500000 -> 125
a: 8000000 -> -192
a: 8500000 -> 347
a: 9000000 -> 29
a: 9500000 -> -289
``````

Despite the prototype is this really only for small ranges?

The board that I’m using is the Leonardo, I’m not sure but that may make a difference if it treats a long as something other than a 32 bit integer like the documentation suggests then I imagine it will.

Thanks.

Ditch the String class and try again. Until you do that, you can't be sure where the problem lies.

This is the implementation of the `max` function (found in `WMath.cpp`):

``````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;
}
``````

Given `x = 5500000` and your other arguments, the product `(x - in_min) * (out_max - out_min)` yields 500,000 x 65,535 = 32,768,000,000, which is far outside a 32-bit `long`'s value range and overflows even before the division is done.

Michael, thanks for pointing that out. I could have sworn I ran a couple of numbers through a calculator but I was either out to lunch or didn't use my actual values. I ended up just writing my own single-purpose map as

``````unsigned int _map(long x) {
return(long(double(x) * 65535.0 / 20000000.0));
}
``````

Thanks.

Oh, any solution where you resort to using floating point arithmetic to avoid overflow in evaluating an integer expression is IMO a bad idea.

It should be possible to reorder the integer arithmetic expression so that it avoids overflow or excessive rounding of the intermediate values. If necessary you can do a scaling divide before you do the multiplication, to avoid the multiplication overflowing. You can also use long long ints if you get desperate.

``````x = map(a, 5 000 000, 10 000 000, 0, 65535);
``````

is equal to

`````` a -= 5000000;
x =  map(a, 0, 5 000 000, 0, 65535);
``````

as both ranges start with 0 the mapping becomes a simple division

``````x = a * 65535 / 5000000;
``````

as both 65535 and 5000000 are a multiple of 5

``````x = a * 13107/ 1000000;
``````

this multiplication will overflow when a has a value of ~160.000 if a very small error is acceptable one could simplify the formula (use a spreadsheet)

``````x = a * 131/9994;
``````

which overflows at values of ~ 16 000 000 which is well beyond the original range of 5M-10M

as a was a - 5 000 000 the final formula becomes

``````x = (a - 5000000) * 131/9994;
``````