Skip to content

Map function returns a negative number for large ranges #10557

Open
@rjp119

Description

@rjp119

For example: map (20000, 0, 40000, 0, 120000) returns -47,374 and should return 60,000. This is clearly a number over run. The issue is the order of operations that is used to calculate the value. Per the documentation, map is defined as:

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

Everything is defined as long, so that's not the problem. If you look at the math for the example above, the map function will execute as follows:

  1. x - in_min = 4,000
  2. out_max - out_min = 120,000
  3. the (x - in_min) * (out_max - out_min) = 2,400,000,000.

Step 3 generates a number that's too big to be stored in a long. This is the overrun.

If map is changed to execute the division first, large numbers during the calculation are avoided. So I suggest map to be changed to add parentheses around the division to execute that first. So map would 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) / (in_max - in_min)) + out_min;
}

For the given example, this would execute as:

  1. out_max - out_min = 4,000
  2. in_max - in_min = 1,200,000
  3. out_max - out_min) / (in_max - in_min = 3
  4. (x - in_min) * ((out_max - out_min) / (in_max - in_min)) = 60,000

Everything fitting within the long variable.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Component: CoreRelated to the code for the standard Arduino APIType: Bug

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions