WEBVTT

1
00:00:00.000 --> 00:00:00.920
こんにちは。

2
00:00:00.920 --> 00:00:04.905
今回はジャバスクリプトのマス・アイマルを紹介します。

3
00:00:04.905 --> 00:00:13.489
これは、二つの値を三十二ビットの整数として掛け算し、符号付き三十二ビット整数として結果を返す標準のメソッドです。

4
00:00:13.489 --> 00:00:18.470
名前ごとに表示色を決めたり、テストデータを複数の処理先へ割り当てたりと、

5
00:00:18.470 --> 00:00:23.452
同じ項目を毎回同じグループへ振り分けたい場面で役立ちます。

6
00:00:23.452 --> 00:00:30.963
普通の掛け算と何が違うのか、なぜ結果が負の数になることがあるのかを、基本から順に確かめていきます。

7
00:00:30.963 --> 00:00:39.700
この動画では、基本コード、文字列を四つのグループへ振り分ける実例、そして通常の掛け算で失敗する例までを解説します。

8
00:00:39.700 --> 00:00:40.964
まず動作環境です。

9
00:00:40.964 --> 00:00:48.688
マス・アイマルはジャバスクリプト標準の組み込みメソッドで、ブラウザーとノード・ジェイエスの両方で利用できます。

10
00:00:48.688 --> 00:00:53.322
二千十五年七月以降、主要ブラウザーで広く利用できる機能とされており、現行のクローム、

11
00:00:53.322 --> 00:00:57.957
エッジ、ファイアフォックス、サファリが対象です。

12
00:00:57.957 --> 00:01:05.540
記事のサンプルはノード・ジェイエス二十二系または二十四系を想定し、追加パッケージや実験的な設定は使いません。

13
00:01:05.540 --> 00:01:12.000
古いブラウザーや組み込みの表示部品では、使う前にタイプオブで関数かどうかを確認してください。

14
00:01:12.000 --> 00:01:18.320
対応していない環境では、コードをそのまま実行せず、対応する環境へ切り替えることが大切です。

15
00:01:18.320 --> 00:01:20.493
基本の書き方を見ましょう。

16
00:01:20.493 --> 00:01:25.508
呼び出し方はマス・アイマル、かっこ、エー、カンマ、ビーです。

17
00:01:25.508 --> 00:01:30.858
エーとビーが掛け算する二つの値で、戻り値はナンバー型の数値です。

18
00:01:30.858 --> 00:01:40.219
結果の範囲はマイナス二十一億四千七百四十八万三千六百四十八から、二十一億四千七百四十八万三千六百四十七までです。

19
00:01:40.219 --> 00:01:43.562
小さな値では通常の掛け算と変わりません。

20
00:01:43.562 --> 00:01:48.912
三かける四は十二、マイナス五かける十二はマイナス六十になります。

21
00:01:48.912 --> 00:01:55.599
マスはコンストラクターではないため、インスタンスを作らず直接呼び出してください。

22
00:01:55.599 --> 00:02:00.948
違いが表れるのは、積がこの範囲を超える大きな計算のときだけです。

23
00:02:00.948 --> 00:02:03.580
桁あふれの仕組みを押さえます。

24
00:02:03.580 --> 00:02:08.318
三十二ビットでは、すべての大きな整数を保持できません。

25
00:02:08.318 --> 00:02:16.741
マス・アイマルは積の下位三十二ビットだけを残し、その並びを符号付き整数として読み直して返します。

26
00:02:16.741 --> 00:02:20.777
範囲を超えたことを知らせる例外は発生しません。

27
00:02:20.777 --> 00:02:28.410
たとえば最大値の二十一億四千七百四十八万三千六百四十七を二倍すると、通常の計算では四十二億九千四百九十六万七千二百九十四ですが、

28
00:02:28.410 --> 00:02:36.043
三十二ビットとして読むとマイナス二になります。

29
00:02:36.043 --> 00:02:39.728
負の数になっても計算の失敗ではありません。

30
00:02:39.728 --> 00:02:45.168
この性質は一定の幅で値を更新する処理に向きますが、商品の合計金額や数量など、

31
00:02:45.168 --> 00:02:50.608
積の大きさをそのまま保ちたい計算には向きません。

32
00:02:50.608 --> 00:02:53.197
基本コードの期待出力を読みます。

33
00:02:53.197 --> 00:02:59.022
ポイントは、入力が三十二ビット整数へ変換されてから掛け算されることです。

34
00:02:59.022 --> 00:03:02.662
小数部分は整数への変換時に取り除かれるため、三点九と二の積は七点八ではなく、

35
00:03:02.662 --> 00:03:06.303
六になります。

36
00:03:06.303 --> 00:03:11.804
また、四十二億九千四百九十六万七千二百九十六は二の三十二乗なので、三十二ビットへの変換後はゼロとして扱われ、

37
00:03:11.804 --> 00:03:17.306
何を掛けても結果はゼロです。

38
00:03:17.306 --> 00:03:24.587
これらの出力はノード・ジェイエスの実機でも確認済みで、記事の期待出力と完全に一致しました。

39
00:03:24.587 --> 00:03:31.868
変換が先、掛け算が後、という順番を意識すると、予想外に見える結果も落ち着いて説明できます。

40
00:03:31.868 --> 00:03:33.600
ここからは活用例です。

41
00:03:33.600 --> 00:03:39.426
文字列を先頭から読み、途中の値を三十一倍して文字の値を足す処理を作ります。

42
00:03:39.426 --> 00:03:43.205
学習用の簡単なハッシュ計算として扱ってください。

43
00:03:43.205 --> 00:03:51.709
バケットフォーという関数は、引数が文字列でなければタイプエラーを投げ、空文字は受け入れてゼロを返す設計です。

44
00:03:51.709 --> 00:03:56.984
本体ではハッシュの初期値をゼロとし、文字ごとにマス・アイマルで三十一倍して文字コードを加え、

45
00:03:56.984 --> 00:04:02.259
最後にパイプゼロで三十二ビットへ収めます。

46
00:04:02.259 --> 00:04:10.290
仕上げに符号なしとして読み直してから四で割った余りを取るため、戻り値はゼロから三までの整数になります。

47
00:04:10.290 --> 00:04:14.856
掛け算にアイマルを使うことが、値の更新を安定させる要です。

48
00:04:14.856 --> 00:04:16.923
振り分け結果を確かめます。

49
00:04:16.923 --> 00:04:20.420
空文字はゼロ、エーは一、ビーは二になります。

50
00:04:20.420 --> 00:04:27.097
エービーシーは二で、同じ文字列をもう一度計算しても必ず二になり、再現性が保たれます。

51
00:04:27.097 --> 00:04:33.773
一方で、ビーとエービーシーのように、異なる文字列が同じグループに入ることもあります。

52
00:04:33.773 --> 00:04:39.655
これは欠陥ではなく、有限のグループへ振り分ける以上は避けられない性質です。

53
00:04:39.655 --> 00:04:46.809
数値でない値を渡した場合は、関数の入り口でタイプエラーとして報告され、計算には進みません。

54
00:04:46.809 --> 00:04:51.101
これらの結果もノード・ジェイエスの実機で確認済みです。

55
00:04:51.101 --> 00:04:56.188
同じ入力に同じ出力、という約束が、この仕組みの価値そのものです。

56
00:04:56.188 --> 00:04:59.324
エービーシーの計算を一歩ずつ追います。

57
00:04:59.324 --> 00:05:03.285
使われるのはユーティーエフ十六のコード単位の値で、エーが九十七、ビーが九十八、

58
00:05:03.285 --> 00:05:07.246
シーが九十九です。

59
00:05:07.246 --> 00:05:11.043
最初はゼロかける三十一に九十七を足して九十七。

60
00:05:11.043 --> 00:05:15.004
次に九十七かける三十一に九十八を足して三千百五。

61
00:05:15.004 --> 00:05:23.091
最後に三千百五かける三十一に九十九を足して九万六千三百五十四となり、四で割った余りが二になります。

62
00:05:23.091 --> 00:05:31.674
途中の足し算の後にも三十二ビットへ収めているため、長い文字列でも値が際限なく大きくなることはありません。

63
00:05:31.674 --> 00:05:38.936
最後の符号なしへの読み直しは、途中の値が負数でも振り分け番号を負にしないための補助です。

64
00:05:38.936 --> 00:05:43.841
失敗例として、通常の掛け算との違いを決定的な例で見ます。

65
00:05:43.841 --> 00:05:52.074
四十二億九千四百九十六万七千二百九十五同士を掛けると、数学的な積は非常に大きな整数になります。

66
00:05:52.074 --> 00:05:55.577
マス・アイマルで計算すれば結果は一です。

67
00:05:55.577 --> 00:06:03.110
ところが通常の掛け算をしてから三十二ビットへ変換すると、結果はゼロになってしまいます。

68
00:06:03.110 --> 00:06:11.868
通常の数値では、この大きな積を正確に保持できず、掛け算の時点で下位の情報が丸められてしまうためです。

69
00:06:11.868 --> 00:06:15.722
後から変換しても、失われた情報は戻りません。

70
00:06:15.722 --> 00:06:24.480
三十二ビットの積が必要な処理では、変換を後付けせず、掛け算そのものにマス・アイマルを使ってください。

71
00:06:24.480 --> 00:06:27.108
この結果も実機で確認済みです。

72
00:06:27.108 --> 00:06:29.214
注意点を二つ整理します。

73
00:06:29.214 --> 00:06:31.319
一つ目は入力の扱いです。

74
00:06:31.319 --> 00:06:38.163
マス・アイマルは、入力が業務上正しい整数かどうかを検証する関数ではありません。

75
00:06:38.163 --> 00:06:45.182
文字列の五は数値の五として変換され、小数も切り捨てられて計算が進んでしまいます。

76
00:06:45.182 --> 00:06:52.552
入力ミスを見逃したくない処理では、呼び出す前に型と許容範囲を自分で検証してください。

77
00:06:52.552 --> 00:06:58.518
ビッグイントを引数に渡すとタイプエラーになるため、桁あふれなしで大きな整数を計算したい場合は、

78
00:06:58.518 --> 00:07:04.485
ビッグイント同士の通常の乗算を検討します。

79
00:07:04.485 --> 00:07:06.590
二つ目は用途の限界です。

80
00:07:06.590 --> 00:07:11.679
今回の振り分け計算は暗号学的なハッシュではないため、パスワードの保存、改ざん検知、

81
00:07:11.679 --> 00:07:16.768
一意な識別子の生成には使えません。

82
00:07:16.768 --> 00:07:18.590
活用場面とまとめです。

83
00:07:18.590 --> 00:07:24.141
名前ごとの色分けでは、四色の配列を用意し、振り分け関数の戻り値を配列の位置として使うだけで、

84
00:07:24.141 --> 00:07:29.691
同じ名前には常に同じ色が割り当てられます。

85
00:07:29.691 --> 00:07:33.501
再現性のあるテストデータの割り当ても同様です。

86
00:07:33.501 --> 00:07:39.300
改善するなら、結果を保存する前に代表的な入力で分布を確認してください。

87
00:07:39.300 --> 00:07:43.442
四つのグループへ均等に分かれる保証はないためです。

88
00:07:43.442 --> 00:07:49.240
また、グループ数や計算規則を変えると既存の割り当ても変わってしまうので、

89
00:07:49.240 --> 00:07:55.039
永続的な割り当てが必要なら、計算結果を記録する設計も検討しましょう。

90
00:07:55.039 --> 00:08:01.169
まずは身近な文字列で試し、三十二ビットで掛ける感覚をつかんでみてください。

91
00:08:01.169 --> 00:08:02.660
お疲れさまでした。
