1
0

JavaScript ランダム値のゼロパディングを少しだけ短く記述

Last updated at Posted at 2023-12-04

今更ながらのネタですが、JavaScriptで数値のゼロパディング、例えばMath.random()の戻り値を元に000999のランダムな整数を得たい場合、先頭に必要桁数の0を付けた上でslice()で後方から切り出す

const randomNum = ('00' + Math.floor(Math.random() * 1000)).slice(-3);
console.log(randomNum);

padStart()を使うなら

const randomNum = String(Math.floor(Math.random() * 1000)).padStart(3, '0');
console.log(randomNum);

辺りが常套手段かと思います。
テンプレートリテラルを使えばもう少し短く、それぞれ

const randomNum = `00${Math.floor(Math.random() * 1000)}`.slice(-3);
console.log(randomNum);
const randomNum = `${Math.floor(Math.random() * 1000)}`.padStart(3, '0');
console.log(randomNum);

といったところでしょうか。

これらを、もう少し簡潔にできないか考えてみます。
0~999の範囲ならMath.floor()の代わりにビット演算で整数化する手もありますが、この範囲はあくまで一例なので、とりあえず今回はビット演算は無しで…

Math.random() の戻り値が 0.07425549624427696 だったとして、
1000倍して 74.25549624427696、それに1000を加えて 1074.25549624427696
そこから 1074.25549624427696 この部分を切り出す考え方で、

const randomNum = `${Math.random() * 1000 + 1000}`.slice(1, 4);
console.log(randomNum);

もうひとつ、1000倍するのも省略して 0.07425549624427696 この部分を切り出す考え方で、

const randomNum = `${Math.random()}`.slice(2, 5);
console.log(randomNum);

Math.random()0.010など、切り出したい桁数に満たない値を返す可能性が無いとも限らないので、

const randomNum = `${Math.random()}0000`.slice(2, 5);
console.log(randomNum);

これで良さそうです。

どの方法でも同じ結果になるか、簡単に確認。

[0, 0.9, 0.09, 0.009, 0.0009, Math.random()].forEach(random => {
  console.log('random: ', random);
  console.log(
    `00${Math.floor(random * 1000)}`.slice(-3),
    `${Math.floor(random * 1000)}`.padStart(3, '0'),
    `${1000 + random * 1000}`.slice(1, 4),
    `${random}0000`.slice(2, 5)
  );
});
random:  0
000 000 000 000
random:  0.9
900 900 900 900
random:  0.09
090 090 090 090
random:  0.009
009 009 009 009
random:  0.0009
000 000 000 000
random:  0.16843531459923278
168 168 168 168

---- 追記

`${Math.random()}0000`.slice(2, 5);

この方法は、Math.random()の戻り値が0.000001を下回った場合に指数表記になってしまうので駄目ですね。

console.log(`${0.000001}0000`.slice(2, 5)); // 000
console.log(`${0.0000009}0000`.slice(2, 5)); // -70

---- 追記終わり

---- 追記2

Math.random()の戻り値が0.000001を下回った場合に指数表記になってしまう

1を足すことで指数表記になるのは避けられそうです。

[0, 0.009, 0.0000009, 0.00000000009, Math.random()].forEach(random => {
  console.log('random: ', random);
  console.log(
    `${1000 + random * 1000}`.slice(1, 4),
    `${random}0000`.slice(2, 5),
    `${1 + random}0000`.slice(2, 5)
  );
});

/*
random:  0
000 000 000
random:  0.009
009 009 009
random:  9e-7
000 -70 000
random:  9e-11
000 -11 000
random:  0.8297180866780045
829 829 829
*/

ただ、ぱっと見で何のための1なのか分かりにくいので、あまり旨味は無さそう。

---- 追記2終わり


別パターンで、日時表記等で正の整数を0埋めしたいケース。

[0, 1, 10, 59].forEach(num => {
  console.log('num: ', num);
  console.log(
    `0${num}`.slice(-2),
    `${num}`.padStart(2, '0')
  );
});
num:  0
00 00
num:  1
01 01
num:  10
10 10
num:  59
59 59

変な小細工をするまでもなく、単純に従来から使われているslice()で後方から切り出す方法やpadStart()を使う方法で十分簡潔だと思います。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0