与えられた数値を 0, 5, 10, 15, … と 5刻みに丸めたい
結論
const get5RoundNumber = (n: number) => Math.round(n * 2 / 10) * 10 / 2;
- 5 刻みの数値を得るには 10 刻み
0,10,20,30, ... を 2 で割れば0,5,10,15, … ととなる 0,10,20,30,… という数字を得るには、四捨五入で0,1,2,3,... を作り 10 倍すれば良い- 最終的に 2 で割るので、もとの数値を 2倍しておく
- 1の位で四捨五入するには 1の位を小数点第一位にするために、10で割れば良い
文章で書いてもわかりにくいので表にする
5 刻みに丸める
| n | * 2 / 10 |
Math.round |
* 10 |
/ 2 (Result) |
|---|---|---|---|---|
| 0 | 0.2 | 0 | 0 | 0 |
| 1 | 0.2 | 0 | 0 | 0 |
| 2 | 0.4 | 0 | 0 | 0 |
| 3 | 0.6 | 1 | 10 | 5 |
| 4 | 0.8 | 1 | 10 | 5 |
| 5 | 10 | 1 | 10 | 5 |
| 6 | 1.2 | 1 | 10 | 5 |
| 7 | 1.4 | 1 | 10 | 5 |
| 8 | 1.6 | 2 | 20 | 10 |
| 9 | 1.8 | 2 | 20 | 10 |
| 10 | 2.0 | 2 | 20 | 10 |
0.5 刻みに丸める
小数点第二位を四捨五入して 0.5 刻みに丸める場合は 10 で割らなければ良い
| n | * 2 |
Math.round |
/ 2 (Result) |
|---|---|---|---|
| 0.0 | 0.2 | 0 | 0 |
| 0.1 | 0.2 | 0 | 0 |
| 0.2 | 0.4 | 0 | 0 |
| 0.3 | 0.6 | 1 | 0.5 |
| 0.4 | 0.8 | 1 | 0.5 |
| 0.5 | 10 | 1 | 0.5 |
| 0.6 | 1.2 | 1 | 0.5 |
| 0.7 | 1.4 | 1 | 0.5 |
| 0.8 | 1.6 | 2 | 1.0 |
| 0.9 | 1.8 | 2 | 1.0 |
| 1.0 | 2.0 | 2 | 1.0 |
桁の調整
- 50 刻みなら
100で割ってMath.roundし、100を掛ける。 - 5 刻みなら
10で割ってMath.roundし、10を掛ける。 - 0.5 刻みなら
1で割ってMath.roundし、10を掛ける。 - 0.05 刻みなら
10を掛けてMath.roundし、10で割る。
桁数 * 10 をした値が、1 以上なら 割って Math.roundし、掛ける、1以下なら 掛けて Math.round し、で割ればよい。
const getAdjustDigits = (n: number) => { const digits = Math.floor(n); if (digits > 0) { return Math.pow(10, digits); } else if (digits < 0) { // 桁数が整数の場合は正、少数の場合は負の数にして返す return -Math.pow(10, Math.abs(digits) - 1); } else { return 0; } } const get5RoundNumber = (n: number, digits: number = 1) => { // 桁数が 0 のとき小数点第一位まで表示する if (digits === 0) { return Math.round(n * 2) / 2; } const x = getAdjustDigits(digits); if (x > 0) { return Math.round(n * 2 / x) * x / 2; } const j = Math.abs(x); return Math.round(n * 2 * j) / j / 2; }
こんな感じで 5 刻みの数値に変換できそう
5 になりやすいので微妙に調整したほうが良い気もするが、ざっくり要件が満たせてると思う
有効桁数のひとつ下の桁数を四捨五入してから 5刻みに変換する
5桁で丸める前に数字を有効桁数の一つ下で四捨五入すれば良い
const getAdjustDigits = (n: number) => { const digits = Math.floor(n); if (digits > 0) { return Math.pow(10, digits); } else if (digits < 0) { // 桁数が整数の場合は正、少数の場合は負の数にして返す return -Math.pow(10, Math.abs(digits) - 1); } else { return 0; } } // 有効桁数の1つ下の桁で四捨五入した数値を返す const getRoundedNumber = (n: number, digits: number, isInteger: boolean = true) => { const d = (isInteger && digits > 1) ? digits / 10 : digits * 10; if (isInteger) { return Math.round(n / d) * d; } return Math.round(n * d) / d; } const get5RoundNumber = (n: number, digits: number = 1) => { // 桁数が 0 のとき小数点第一位まで表示する if (digits === 0) { return Math.round(n * 2) / 2; } const x = getAdjustDigits(digits); const j = Math.abs(x); const roundN = getRoundedNumber(n, j, x > 0); if (x > 0) { return Math.round(roundN * 2 / x) * x / 2; } return Math.round(roundN * 2 * j) / j / 2; }
Sample
See the Pen 5 round number by KIKIKI (@kikiki_kiki) on CodePen.
おわり

