Number Conversion
Ratio Preservation
Mathematical Scaling
Range Mapping
Numerical Transformation

Convert a number range to another range, maintaining ratio

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Converting a number from one range into another while preserving the ratio is a standard linear-mapping problem. The core idea is simple: first normalize the value inside the original range, then scale that normalized value into the target range.

The Standard Formula

To map a value x from source range [a, b] into target range [c, d], use:

text
((x - a) / (b - a)) * (d - c) + c

This keeps the relative position of the value the same in the new range.

For example, mapping 25 from [0, 100] into [0, 50] gives 12.5, because 25 is one quarter of the way through the original range and 12.5 is one quarter of the way through the new range.

Python Implementation

python
1def remap(x, src_min, src_max, dst_min, dst_max):
2    if src_max == src_min:
3        raise ValueError("source range cannot be zero-width")
4
5    return ((x - src_min) / (src_max - src_min)) * (dst_max - dst_min) + dst_min
6
7
8print(remap(25, 0, 100, 0, 50))   # 12.5
9print(remap(75, 0, 100, -1, 1))   # 0.5

This works for integers and floats as long as the source range has nonzero width.

Think in Two Steps: Normalize, Then Scale

The formula is easier to remember if you split it conceptually:

  1. convert the value to a normalized ratio between 0 and 1,
  2. expand that ratio into the destination range.

In code:

python
def remap_verbose(x, src_min, src_max, dst_min, dst_max):
    ratio = (x - src_min) / (src_max - src_min)
    return dst_min + ratio * (dst_max - dst_min)

That version is mathematically identical, but easier to explain to future readers.

Reversed Ranges Also Work

The same formula works even if one of the ranges is reversed. For example, mapping from [0, 100] to [1, 0] flips the direction.

python
print(remap(0, 0, 100, 1, 0))    # 1.0
print(remap(100, 0, 100, 1, 0))  # 0.0
print(remap(25, 0, 100, 1, 0))   # 0.75

This is useful for UI sliders, screen coordinates, and score inversions where larger source values should become smaller destination values.

Decide Whether to Clamp

The basic formula does not clamp values. If x lies outside the source range, the output will lie outside the destination range too.

Sometimes that is correct. Sometimes you want clamping:

python
def remap_clamped(x, src_min, src_max, dst_min, dst_max):
    x = max(src_min, min(src_max, x))
    return remap(x, src_min, src_max, dst_min, dst_max)

Choose explicitly. Silent clamping and silent extrapolation mean different things in different applications. Good range-mapping helpers make that choice obvious instead of hiding it. That makes later bugs much easier to reason about. Clear scaling rules save time later. They also make helper functions easier to trust. That consistency helps.

Common Pitfalls

  • Forgetting to handle the zero-width case where src_min == src_max.
  • Assuming the formula automatically clamps out-of-range values.
  • Rewriting the math ad hoc each time instead of using one tested helper.
  • Getting the subtraction order wrong and flipping the mapping unintentionally.
  • Using integer division accidentally in languages or runtimes where that changes the result.

Summary

  • Range conversion with ratio preservation is a linear mapping problem.
  • The standard formula is ((x - a) / (b - a)) * (d - c) + c.
  • Think of it as normalize first, then scale into the target range.
  • The same formula works for reversed ranges.
  • Decide explicitly whether your application wants clamping or extrapolation.

Course illustration
Course illustration

All Rights Reserved.