Value Remapping

From your description, it ought to be doing this, right?

low2 + (value - low1) * (high2 - low2) / (high1 - low1)

Find how far you are into the first range, scale that distance by the ratio of sizes of the ranges, and that's how far you should be into the second range.


Processing is open-source. You can view the map() function here.

static public final float map(float value,
                                float start1, float stop1,
                                float start2, float stop2) {
    float outgoing =
      start2 + (stop2 - start2) * ((value - start1) / (stop1 - start1));
    String badness = null;
    if (outgoing != outgoing) {
      badness = "NaN (not a number)";

    } else if (outgoing == Float.NEGATIVE_INFINITY ||
               outgoing == Float.POSITIVE_INFINITY) {
      badness = "infinity";
    }
    if (badness != null) {
      final String msg =
        String.format("map(%s, %s, %s, %s, %s) called, which returns %s",
                      nf(value), nf(start1), nf(stop1),
                      nf(start2), nf(stop2), badness);
      PGraphics.showWarning(msg);
    }
    return outgoing;
  }

Specifically, you're looking for this line of code:

float outgoing =
      start2 + (stop2 - start2) * ((value - start1) / (stop1 - start1));

I would like to add that is sometimes useful to find the factor between the low1 and high1 so that you can modulate it with a curve before using the factor as a LERP's t.

So, t = (value-low1)/(high1-low1) to get the relative position of value in the line low1 to high1.

Then you can modulate t with some curve filter for example, gamma, bias, gain, etc As also clamp the t between 0 and 1 if you to restrict values that go over the set lows and highs.

And then use the t for the LERP between low2 and high2 like: finalvalue = low2*(1-t) + high2*t


Anyone wondering if there's a float-less version that keeps as much precision as possible, I made this:

int remap(int value, int input_min, int input_max, int output_min, int output_max)
{
    const long long factor = 1000000000;

    long long output_spread = output_max - output_min;
    long long input_spread = input_max - input_min;

    long long l_value = value;

    long long zero_value = value - input_min;
    zero_value *= factor;
    long long percentage = zero_value / input_spread;

    long long zero_output = percentage * output_spread / factor;

    long long result = output_min + zero_output;

    return (int)result;
}

Seems to work for me, not extensively tested (e.g. max is smaller than min is not tested).

The idea behind is it to enlarge the original value by using a bigger type so that divisions yield bigger numbers - which results in more precision.