質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

浮動小数点

浮動小数点は、コンピュータが数値を扱う際に実数を表現する方法のひとつです。 数値を、それぞれの桁の値が並んでいる仮数部と、小数点の場所を示す指数部で表します。

Q&A

解決済

1回答

1287閲覧

Math.random() の境界上限値の出力に関して

退会済みユーザー

退会済みユーザー

総合スコア0

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

浮動小数点

浮動小数点は、コンピュータが数値を扱う際に実数を表現する方法のひとつです。 数値を、それぞれの桁の値が並んでいる仮数部と、小数点の場所を示す指数部で表します。

2グッド

3クリップ

投稿2021/07/05 23:22

編集2021/07/06 04:06

MDN の Math.random() の説明を読んでいると、以下の記述がありました。

JavaScript における数値は、IEEE 754 浮動小数点での round-to-nearest-even を行うため、以下の関数の値域が ( Math.random() 自体の値域が正しくても) 厳密ではないことに注意してください。非常に大きい境界値 (2 の 53 乗以上) のうち極めて稀な数値で、通常なら返されないはずの上限値が出力されてしまうことがあり得ます。

このコメントを素直に読むと
Math.random() * numnum = 2 ** 53 以上の範囲で上限値 num が出力される
と読めるのですが、
Math.random() * numnum = 2 ** 53 以上の特定の数で上限値 num が出力される
とも読めます。

正しくはどういった内容なのでしょうか?
ご教授いただければ幸いです。

Lhankor_Mhy, BeatStar👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2021/07/05 23:29

ケチビットの問題ですよね? Math.random() * num が特定の数になった時、計算上は奇数のはずなのに偶数になるということではありませんか? 偶数はそのままその数になるので、「全てが」とはならないと思いますが、そういう質問ですか?
退会済みユーザー

退会済みユーザー

2021/07/05 23:36

ケチビットの問題という呼称をそもそも知りませんでした。 その辺からよくわかっていないで、少し調べてみます。 ありがとうございます。
Zuishin

2021/07/05 23:46

すみません、「ケチビット」より「ケチ表現」の方が伝わりやすかったと思います。
退会済みユーザー

退会済みユーザー

2021/07/06 04:07 編集

「ケチ表現」「ケチビット」で調査してみましたが、質問との関連性が分かりませんでした。 。。。という事は、そもそも > Math.random() * num で num = 2 ** 53 以上の範囲で上限値 num が出力される > Math.random() * num で num = 2 ** 53 以上の特定の数で上限値 num が出力される の想定すら全然的外れなんですかね^^; もう少し調べてみます。
退会済みユーザー

退会済みユーザー

2021/07/06 04:07

質問が 2**23 になってました^^;53に修正しました。
Zuishin

2021/07/06 04:13

外したかもしれません。 最終ビットが必ず 1 なので、それを丸めて偶数にしようとすると、計算上最終ビットが 0 であったはずの数の場合は誤差が大きくなり、乱数の最大値未満の数が出力されるはずが最大値以下の値になってしまうことがあるということではないかと考えました。
退会済みユーザー

退会済みユーザー

2021/07/06 04:16

記述いただいた方向性は理解しました。 が、中身は理解できていないので、調査の一部として継続してみますw
hihijiji

2021/07/06 07:35 編集

Math.random() * num にて num >= 2 ** 53 のとき極めて稀に上限値 num が出力される つまり Math.random() * numの結果如何によってはround-to-nearest-evenにて切り上げられちゃう ってことでは?
退会済みユーザー

退会済みユーザー

2021/07/06 08:22 編集

はい。そのように読み取りました。 hihijiji さんが書いてくれたのが、私が最初に思い浮かべた前者ですね。 ただ、原理が分かっていないので、もしかしたら後者の可能性もあるのかと。(そのようにも読み取れる) どっかに仕様の分かるドキュメントが転がってるとイイのですけど、ざっと見た感じ、ないんですよね^^; 最終的には算数で検証するつもりです。。。
guest

回答1

0

ベストアンサー

Math.random() * num

いいえ。挙げられている式はMath.random() * (max - min) + min;です。

そして特定のmax,minの組でのみ発生するようです。
きちんとした証明はしていませんが、普通に考えて、
「問題が発生しうるならrandomが最大値の時には必ず発生し、逆にrandomが最大値の時に発生しなければrandomが他の値の時には必ず発生しない」
でしょう。
その上で、例えばmax=2**53+4, min=1の時発生し、max=2**53, min=0の時発生しませんでした。

中間の値を追うと、(2**53=0x20_0000_0000_0004を0x20...04のように略記します)
0x20...04 - 1は0x20...03で、丸められて 0x20...04。
0x20...04 * 0.999...は0x20...03弱で、丸められて0x20...02。
0x20...02 + 1は0x20...03で、丸められて 0x20...04。
となります。

投稿2021/07/07 13:15

ikadzuchi

総合スコア3047

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/07/07 21:12 編集

回答ありがとうございます。 という事は、倍精度浮動小数点数の外側、つまり SafeInteger で無いため、足し算の部分で不整合が発生し、Math.random() の上限の境界値が出力されてしまうケースがあるという事ですかね? なんで、Math.random() だけ態々ドキュメントに記述があるんだろ。。。 まだちょっと理解できていない箇所もあるので、いただいた回答をもう少し自分でも検証してみます。
ikadzuchi

2021/07/10 04:51

「倍精度浮動小数点数の外側」は意味が通らないので何かの間違いかと思いますが、「SafeInteger で無いため」が原因で、 「足し算の部分で」もそうですが引き算の部分でも、 「不整合」というのは少々違和感がありますが、丸めによる誤差が2回同じ方向に出ているために、 「Math.random() の」ではなく、下で定義されたgetRandomArbitrary(min, max)やgetRandomInt(min, max)の、上限の境界値が出力されてしまうケースがあるわけです。
退会済みユーザー

退会済みユーザー

2021/07/12 20:32

> 「倍精度浮動小数点数の外側」は意味が通らないので何かの間違いかと思います はい。間違いですね^^; まだ、「Math.random() だけ態々ドキュメントに記述がある」の部分が理解できていないのですが、間違いの指摘もあり、ずいぶん理解が進みました。 もう少し理解が進めばクローズできそうです。 ありがとうございます。
退会済みユーザー

退会済みユーザー

2021/09/19 00:28

こちら、放置気味になってしまい申し訳ありません。 隙間時間で色々ドキュメントあさってみましたが、回答いただいたように Math.random() * (max - min) + min; に対しての文言を Math.random() * num に対してと勘違いして読み取ったと考えて良さそうです。 ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問