If you have ever made a chart library in your life, you’ve probably asked yourself how to find the best scale for the grid in order to have **nice values to display in the axis**.

Most of the time, **data ranges are unknown**, hence we need to **adapt the grid step** to provide the best display.

## Check this out

Let’s explain the algorithm…

## About scientific notation

Any number can be formatted in scientific notation. It is written in the form of **A x 10N** and is noted **AeN**.

For instance, 2300 becomes **2.3e3** (because 2300 = 2.3 x 103), 12 becomes **1.2e1**, and 0.23 becomes **2.3e-1**.

Scientific notation is exactly made for **displaying huge or tiny values in a few characters**.

We can use the same principle for finding good values for the step scale, we can just **keep the pow of 10** part (**N**) and **round the value part** (**A**).

## Magic numbers

But **rounding is not enough**, I have found that good pattern numbers of step range is those divisible by 2, 5 and 10.

In math term, we need to find a step range *sr*, where

```
∀ n ∈ |N, ∀ a ∈ {1, 2, 5}, ∃ sr, sr = a x 10^n
```

This is basically because 2 x 5 = 10 : using a step of 5 we have a 10 modularity every 2 step, and, using a step of 2 we have a 10 modularity every 5 step.

** 2 step:** 0 2 4 6 8 **10** 12 14 16 18 **20** …

** 5 step:** 0 5 **10** 15 **20** 25 **30** 35 **40** 45 …

**10 step:** **0 10 20 30 40 50 60 70 80 90** …

For any dataset, we need to fallback on the closest step range in all of possible step ranges: … 0.002, 0.02, 0.2, 2, 20, 200, …, … 0.005, 0.05, 0.5, 5, 50, 500, …, and … 0.001, 0.01, 0.1, 1, 10, 100, …,

### Calculate the pow of 10

To get the **N** value of the **A x 10N** form, we can use the log of 10:

```
N = Math.log(number) / Math.log(10)
```

### Calculate the value modulo 10

To get the **A** value of the **A x 10N** form, we can just divide the number by **10N**:

```
A = number / Math.pow(10, N)
```

### ‘Rounding’ the number

We know just need to change the value of **A** and make it more “readable”.

We can map the value as follow:

```
if A ∈ [0, 1.5[ then A becomes 1
if A ∈ [1.5, 3.5[ then A becomes 2
if A ∈ [3.5, 7.5[ then A becomes 5
if A ∈ [7.5, 10[ then A becomes 10
```

Note that these rules may probably be improved, I would love if someone could improve this (because I use a arithmetic mean approach and it should probably be arithmetic).

## Implementation

### Scala

### Javascript

**Usage example:**

```
GridUtils.findNiceRoundStep (xMax, 10)
```

where *xMax* is the scale of the axis, and *10* is the desired number of graduation split.

## Conclusion

Finding the best grid step is finally a simple thing to implement but is an essential feature every chart libraries should have.