Skip to content

map() function equation wrong #51

Open

Description

EDIT NOTE: I added a comment to the end of this from a later comment because I thought it should have been included in the first place.

The equation in the function stated at http://arduino.cc/en/Reference/Map

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

is wrong. The example given:

val = map(val, 0, 1023, 0, 255);

In this example 0-1023 is mapped to 0-255. The equation gets it wrong by mapping 1023 numbers to 255 numbers, when it should be mapping 1024 numbers to 256 numbers.

0 through 1023 is 1024 numbers not 1023 : in_max - in_min : 1023-0=1023
0 through 255 is 256 numbers not 255 : out_max - out_min : 255-0=255

The corrected equation in the function should be:

long map(long x, long in_min, long in_max, long out_min, long out_max)
{
  return (x - in_min) * (out_max - out_min + 1) / (in_max - in_min + 1) + out_min;
}

In the following simpler example it will be easier to see:

val = map(val, 0, 3, 0, 1);

In this example 0,1,2 and 3 is mapped to 0 and 1. Mapped correctly it should be:

0 maps to 0
1 maps to 0
2 maps to 1
3 maps to 1

Using the equation in the the function as it is now, it is mapped as such:

0 maps to 0
1 maps to 0
2 maps to 0
3 maps to 1

This is a common problem programmers have dealt with before. When dealing with arrays you can not determine array size by simply subtracting first position from last position you will always be off by 1. That is why you add 1 to get proper size. I know this is for the most part a minor problem, but if your project requires accurate results this could be a serious issue.

--- Added from later comment---

To give a real world scenario as to why this needs changed consider this. You are using the arduino with a sensor to sample data and based on this data set a servo into 1 of 4 positions. The arduino uses a 10 bit adc and outputs integers from 0 to 1023. You would use map(x, 0, 1023, 1, 4). With the map function as it is currently the only time position 4 would be active is when the arduino outputs the integer 1023. With my proposed change each position would get an equal share of the possible range. When they converted this function from a float function to an integer function they didn't consider that the output is no longer a value but a position. Value mapping maps one value to another and the function works perfectly for floats. Positional mapping distributes the input as evenly as possible to the output and the function as is doesn't do that.

This function needs to be split into two functions. One for floats as it is now and one for integers as I proposed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions