WEBVTT

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

2
00:00:00.877 --> 00:00:04.970
今回はジャバスクリプトのマス・エフラウンドを紹介します。

3
00:00:04.970 --> 00:00:11.548
これは、数値を三十二ビット単精度浮動小数点で表せる値へ丸める、標準の組み込みメソッドです。

4
00:00:11.548 --> 00:00:16.371
ジャバスクリプトの数値は通常、六十四ビットの倍精度で保持されます。

5
00:00:16.371 --> 00:00:23.680
一方、フロート・サーティツー・アレイのような三十二ビットの保存先では、表せる値の細かさが変わります。

6
00:00:23.680 --> 00:00:30.258
そのため、保存した値を元の入力とそのまま比べると、同じつもりでも一致しないことがあります。

7
00:00:30.258 --> 00:00:36.836
マス・エフラウンドで入力側も同じ精度に丸めてから比べれば、保存後の値と正しく照合できます。

8
00:00:36.836 --> 00:00:40.490
この動画では、その仕組みと注意点を順に解説します。

9
00:00:40.490 --> 00:00:45.460
まずは、保存したときに値が変わる理由から、順に確かめていきましょう。

10
00:00:45.460 --> 00:00:46.810
まず動作環境です。

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

12
00:00:55.362 --> 00:01:00.313
二千十五年七月から主要ブラウザー間で広く利用できる機能とされており、現行のクローム、

13
00:01:00.313 --> 00:01:05.265
エッジ、ファイアフォックス、サファリで使えます。

14
00:01:05.265 --> 00:01:11.116
ドムや外部パッケージには依存しないため、同じコードを両方の環境で実行できます。

15
00:01:11.116 --> 00:01:15.917
記事のサンプルはノード・ジェイエス二十二以降を対象としています。

16
00:01:15.917 --> 00:01:22.369
古い組み込みブラウザーで使う場合は、タイプオブで関数かどうかを事前に確認してください。

17
00:01:22.369 --> 00:01:28.520
対応しているかどうかを最初に確かめておくと、環境による違いで悩む時間を減らせます。

18
00:01:28.520 --> 00:01:30.775
基本の書き方を見ましょう。

19
00:01:30.775 --> 00:01:35.458
呼び出し方はマス・エフラウンド、かっこ、バリューです。

20
00:01:35.458 --> 00:01:42.049
引数に数値を一つ渡すと、三十二ビット単精度で表せる、最も近い数値が返ります。

21
00:01:42.049 --> 00:01:48.033
たとえば一点五はそのまま一点五ですが、ゼロ点一はゼロ点一ゼロゼロゼロゼロゼロゼロ一四九ゼロ一一六一二のように、

22
00:01:48.033 --> 00:01:54.017
わずかにずれた値になります。

23
00:01:54.017 --> 00:01:58.527
一点三三七も同様に、末尾までぴったりにはなりません。

24
00:01:58.527 --> 00:02:05.811
マスはコンストラクターではないため、インスタンスを作る必要はなく、直接呼び出します。

25
00:02:05.811 --> 00:02:10.668
戻り値の型はナンバーのままで、元の変数は変更されません。

26
00:02:10.668 --> 00:02:12.965
丸め方と特別な値を確認します。

27
00:02:12.965 --> 00:02:16.028
通常は、最も近い表現可能な値へ丸めます。

28
00:02:16.028 --> 00:02:21.081
ちょうど中間に位置する場合は、偶数丸めと呼ばれる規則が使われます。

29
00:02:21.081 --> 00:02:26.900
入力が大きすぎると、結果がインフィニティ、つまり無限大になる場合があります。

30
00:02:26.900 --> 00:02:33.026
エヌエーエヌはエヌエーエヌのまま返り、プラスゼロとマイナスゼロは符号を保ちます。

31
00:02:33.026 --> 00:02:37.697
ここで大切なのは、マス・エフラウンドを一度呼んだだけでは、その後の計算全体が三十二ビットになるわけではない、

32
00:02:37.697 --> 00:02:42.367
という点です。

33
00:02:42.367 --> 00:02:47.114
丸めが必要な位置で、その都度呼び出す関数だと理解してください。

34
00:02:47.114 --> 00:02:52.168
この性質を知っておくと、特殊な入力でも結果を予測しやすくなります。

35
00:02:52.168 --> 00:02:56.311
フロート・サーティツー・アレイとの関係を見ましょう。

36
00:02:56.311 --> 00:03:01.172
この配列の各要素は三十二ビットで保存されるため、六十四ビットの入力を入れると、

37
00:03:01.172 --> 00:03:06.032
保存の時点で三十二ビットの値へ丸められます。

38
00:03:06.032 --> 00:03:11.450
たとえばゼロ点一を保存して読み戻すと、ゼロ点一ゼロゼロゼロゼロゼロゼロ一四九ゼロ一一六一二になり、

39
00:03:11.450 --> 00:03:16.868
元のゼロ点一とはイコールになりません。

40
00:03:16.868 --> 00:03:23.721
ところが入力側にもマス・エフラウンドを適用すると、保存値と一致してトゥルーになります。

41
00:03:23.721 --> 00:03:29.298
つまりマス・エフラウンドは、保存先の精度を先に再現するための関数です。

42
00:03:29.298 --> 00:03:32.167
この考え方が、今回の中心になります。

43
00:03:32.167 --> 00:03:36.788
保存先と比べるときは、精度をそろえることが何より大切です。

44
00:03:36.788 --> 00:03:38.743
ここからは完成例です。

45
00:03:38.743 --> 00:03:49.230
トゥー・フィニット・フロート・サーティツーという関数は、値を受け取り、検証してからマス・エフラウンドで丸めて返します。

46
00:03:49.230 --> 00:03:57.407
最初に、型がナンバーで、かつ有限の数値かどうかを確かめ、問題があればタイプエラーを投げます。

47
00:03:57.407 --> 00:04:00.073
文字列は自動では変換しません。

48
00:04:00.073 --> 00:04:04.694
次に丸めを行い、その結果も有限かどうかを確認します。

49
00:04:04.694 --> 00:04:12.160
有限の入力でも、丸めた結果が無限大になる場合があるため、変換後の検査が欠かせません。

50
00:04:12.160 --> 00:04:15.359
問題があればレンジエラーを投げます。

51
00:04:15.359 --> 00:04:21.936
検証と変換を一つの関数にまとめると、呼び出し側の処理がシンプルになります。

52
00:04:21.936 --> 00:04:26.021
保存値との比較を、具体的な数で確かめます。

53
00:04:26.021 --> 00:04:28.744
入力は一六七七七二一七です。

54
00:04:28.744 --> 00:04:34.191
六十四ビットでは正確に保持できますが、この付近の三十二ビット浮動小数点では、

55
00:04:34.191 --> 00:04:39.638
表現できる整数の間隔が二になります。

56
00:04:39.638 --> 00:04:47.808
入力はちょうど中間に位置するため偶数丸めが働き、保存値は一六七七七二一六になります。

57
00:04:47.808 --> 00:04:52.477
そのため保存値と入力を直接比べるとフォルスです。

58
00:04:52.477 --> 00:04:58.507
一方、入力側にも同じ丸めを適用して比べるとトゥルーになります。

59
00:04:58.507 --> 00:05:08.428
これが記事の中心例で、ノード・ジェイエスの実機でも、記事の期待出力と完全に一致することを確認済みです。

60
00:05:08.428 --> 00:05:10.928
期待出力をまとめて読みましょう。

61
00:05:10.928 --> 00:05:14.913
入力一六七七七二一七に対して、保存値は一六七七七二一六、直接比較はフォルス、

62
00:05:14.913 --> 00:05:18.898
丸め後比較はトゥルーです。

63
00:05:18.898 --> 00:05:24.290
さらに、一六七七七二一六と一六七七七二一七という異なる入力をそれぞれ丸めると、

64
00:05:24.290 --> 00:05:29.681
どちらも同じ値になり、別の入力が一致、もトゥルーになります。

65
00:05:29.681 --> 00:05:37.339
不正な入力については、文字列を渡すとタイプエラー、大きすぎる値を渡すとレンジエラーが表示されます。

66
00:05:37.339 --> 00:05:41.402
出力の各行が、精度の違いと検証の役割を示しています。

67
00:05:41.402 --> 00:05:45.622
一行ずつ、どの処理の結果なのかを追って読んでください。

68
00:05:45.622 --> 00:05:51.560
数値を声に出して追うと、丸めの前後で何が変わったのかが分かりやすくなります。

69
00:05:51.560 --> 00:05:55.943
失敗例として、一致の意味の取り違えに注意しましょう。

70
00:05:55.943 --> 00:06:04.033
マス・エフラウンド同士の比較がトゥルーでも、それが示すのは三十二ビットへ丸めた値の一致だけです。

71
00:06:04.033 --> 00:06:07.742
元の値が完全に同じだったことは保証しません。

72
00:06:07.742 --> 00:06:15.495
先ほどの一六七七七二一六と一六七七七二一七のように、丸めによって区別が消えてしまうからです。

73
00:06:15.495 --> 00:06:22.743
識別子、件数、金額など、整数の正確さが必要なデータへ一律に適用するのは避けてください。

74
00:06:22.743 --> 00:06:28.980
元のデータを残す必要がある場合は、丸める前の値を別に保持しておきましょう。

75
00:06:28.980 --> 00:06:31.347
入力検証と精度の制約です。

76
00:06:31.347 --> 00:06:37.902
マス・エフラウンドに文字列などを渡すと、数値への暗黙の変換が行われます。

77
00:06:37.902 --> 00:06:46.096
変換できない文字列はエヌエーエヌになり、ビッグイントやシンボルはタイプエラーを起こします。

78
00:06:46.096 --> 00:06:53.561
数値を受け取る設計なら、呼び出す前に型を検査すると入力ミスを見つけやすくなります。

79
00:06:53.561 --> 00:07:02.665
また、有限の数値でも丸めた結果が無限大になる場合や、非常に小さい値がゼロへ丸められる場合があります。

80
00:07:02.665 --> 00:07:08.037
完成例の関数はゼロへの変化までは拒否しないため、微小な値の消失が問題になる用途では、

81
00:07:08.037 --> 00:07:13.408
許容範囲の検査を追加してください。

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

83
00:07:15.238 --> 00:07:20.146
マス・エフラウンドが実用的なのは、三十二ビットで保存する計測値や描画用データについて、

84
00:07:20.146 --> 00:07:25.054
保存後の値と照合したい場面です。

85
00:07:25.054 --> 00:07:32.873
一方、実際の測定値同士が十分近いかを調べる用途では、保存精度の一致だけでは要件を満たせません。

86
00:07:32.873 --> 00:07:37.365
機器の精度や業務上の許容差に応じた比較が別途必要です。

87
00:07:37.365 --> 00:07:44.353
導入前に、保存形式として同じ値か、と、業務上同じとみなせる値か、を整理してください。

88
00:07:44.353 --> 00:07:47.680
前者にはマス・エフラウンドが役立ちます。

89
00:07:47.680 --> 00:07:55.500
比較の目的を関数名やコメントに残しておくと、後から処理を変更するときにも判断しやすくなります。

90
00:07:55.500 --> 00:08:00.491
まずは小さな値で試し、保存値と比べる感覚をつかんでください。

91
00:08:00.491 --> 00:08:01.988
お疲れさまでした。
