【WTR様により解決済み】(Math.random() * 3) + 1について

nekunyan
記事: 22
登録日時: 2021年5月27日(木) 15:34

【WTR様により解決済み】(Math.random() * 3) + 1について

投稿記事 by nekunyan »

ステータスを参照しないで乱数ダメージを与えたくて調べたら

(Math.random() * 3) + 1

を見つけたました
1~3の中からランダムでダメージを与える
と書いてある通りだったのですが

(Math.random() * 20) + 16

にした場合
16~20の間で収まらず20を超えてしまう(26など)のですがなぜでしょうか?
よろしくお願いします
最後に編集したユーザー nekunyan [ 2021年6月28日(月) 14:48 ], 累計 1 回
souma
記事: 35
登録日時: 2019年1月07日(月) 00:37

Re: (Math.random() * 3) + 1について

投稿記事 by souma »

(Math.random() * 5) + 16
で16~20になります。

(Math.random() * 20) + 16
だと16~35が範囲になりますね。

http://rpgmaker-script-wiki.xyz/mvscriptwiki.php#7
こちらの「変数の操作」項目で解説されています。
nekunyan
記事: 22
登録日時: 2021年5月27日(木) 15:34

Re: (Math.random() * 3) + 1について

投稿記事 by nekunyan »

souma さんが書きました:(Math.random() * 5) + 16
で16~20になります。

(Math.random() * 20) + 16
だと16~35が範囲になりますね。

http://rpgmaker-script-wiki.xyz/mvscriptwiki.php#7
こちらの「変数の操作」項目で解説されています。
回答ありがとうございます

昔から算数や数学がどうしても苦手で
この手の計算式がなかなか理解できないもので

回答いただいたものやリンク先を見て
自分なりに解釈したので掲載します

(Math.random() * 20) + 16
を例にします

単純に計算とするために数字のみにします

20 + 16

右の数字が最低値
(今回は16)

まずはそのまま足す

20 + 16 = 36

これで見ると最低値が16最高値が36に思えたんですが

(Math.random() * 20) + 16
だと16~35が範囲になりますね。

書いてある通り実際は35が最高値になります

次にリンク先の式

//40~100までの乱数を発生させる
Math.floor( Math.random() * 61) + 40
→Math.floorの部分はあってもなくても影響なしと思われる

同じように解体して計算をする

61 + 40 = 101

これもまた実際の最高値は100になる

この2つで共通することは
単純に足して-1するのが最高値になっている
ということです

なぜ-1するかどうかに関しては自分ではわからなかったのですが
恐らく他の式にしても同じように-1が最高値になると解釈しました

テストプレイで何十何百と使用してないのでわからないですが
数回してる限りではその想定通りの乱数でダメージが出せてました

文章が読みにくかったら申し訳ありません
もしこの解釈で間違っていたら教えていただきたいです

解釈は違っても結果として-1が最高値になるのであれば
そういうものとして深く考えないようにしようと思います

よろしくお願いします
アバター
WTR
記事: 625
登録日時: 2015年12月22日(火) 19:14

Re: (Math.random() * 3) + 1について

投稿記事 by WTR »

nekunyan さんが書きました://40~100までの乱数を発生させる
Math.floor( Math.random() * 61) + 40
→Math.floorの部分はあってもなくても影響なしと思われる
あってもなくても影響ないのはゲーム変数に入れたときだけです。
イベントコマンドの変数の操作で代入するとき
内部的には setValue() というメソッドが呼ばれますが、このメソッドが実は Math.floor() を一緒にやっています。

変数1にMath.random() * 5
変数2にMath.random() * 5
を入れた場合、変数1も変数2もどちらも切り捨て処理されて最大値が 4 になるため
変数1 + 変数2 は 8 以下の値しかとりませんが

変数1 に Math.random() * 5 + Math.random() * 5
を入れた場合は 足してから切り捨て処理になるため、9 をとる場合があります。
Twitter、はじめました。
https://twitter.com/wtr_in_reverie/
nekunyan
記事: 22
登録日時: 2021年5月27日(木) 15:34

Re: (Math.random() * 3) + 1について

投稿記事 by nekunyan »

WTR さんが書きました:
nekunyan さんが書きました://40~100までの乱数を発生させる
Math.floor( Math.random() * 61) + 40
→Math.floorの部分はあってもなくても影響なしと思われる
あってもなくても影響ないのはゲーム変数に入れたときだけです。
イベントコマンドの変数の操作で代入するとき
内部的には setValue() というメソッドが呼ばれますが、このメソッドが実は Math.floor() を一緒にやっています。

変数1にMath.random() * 5
変数2にMath.random() * 5
を入れた場合、変数1も変数2もどちらも切り捨て処理されて最大値が 4 になるため
変数1 + 変数2 は 8 以下の値しかとりませんが

変数1 に Math.random() * 5 + Math.random() * 5
を入れた場合は 足してから切り捨て処理になるため、9 をとる場合があります。

回答ありがとうございます

すいません理解力が乏しく難しいんですが
今何度かスキルのテストをしてて想定と違ったのでまた掲載しようとしてました

8 以下の値しかとりませんが
9 をとる場合があります

この2つを見てちょうど今の問題と関係ありそうな現象が起こってました

(Math.random() * 6) + 25

この式で何度かしていたのですが
基本は上記にある解釈通り

6 + 25 = 31 - 1 = 30

つまり25~30がほとんどだったのが
たまに31になることがありました

仰っていることを自分なりに解釈すると

Math.floor

があるかどうかで
所謂”未満”と”以下”のような感じになってしまうんでしょうか?

(Math.random() * 6) + 25

だと6 + 25 = 31

Math.floor( Math.random() * 6) + 25

だと6 + 25 = 31 - 1 = 30
ということでいいんでしょうか?

自分の考えではそういう感じでわかりやすくしないと
理解できないもので申し訳ないです

もし見当違いな解釈であったらすいません
よろしくお願いします
アバター
WTR
記事: 625
登録日時: 2015年12月22日(火) 19:14

Re: (Math.random() * 3) + 1について

投稿記事 by WTR »

nekunyan さんが書きました:つまり25~30がほとんどだったのが
たまに31になることがありました
そんなはずはないと思いますが…

Math.random() * 6 は最大で0.99... * 6 = 5.99...
これに 25 を足しても 30.99... にしかなりません。切り捨てれば30にしかならないはずです。
やっていることをそのまま全部見せてもらえれば確認できると思います。
変数の操作ではないのですかね?
添付ファイル
キャプチャ.PNG
キャプチャ.PNG (8.83 KiB) 閲覧された回数 3359 回
Twitter、はじめました。
https://twitter.com/wtr_in_reverie/
ecf5DTTzl6h6lJj02
記事: 752
登録日時: 2018年12月23日(日) 13:55

Re: (Math.random() * 3) + 1について

投稿記事 by ecf5DTTzl6h6lJj02 »

こんにちは。
横から失礼します。
nekunyan さんが書きました: (Math.random() * 6) + 25

この式で何度かしていたのですが
基本は上記にある解釈通り

6 + 25 = 31 - 1 = 30

つまり25~30がほとんどだったのが
たまに31になることがありました
恐らく、浮動小数点の丸め誤差によるものです。
コンピュータでは、数値を2進法で表す関係上、小数点をうまく表すことができずに、誤差が生じることがあります。
このため、浮動小数点数を含んだ計算結果が正確な数値にならない可能性があります。
例えば、

コード: 全て選択

a = 0.999999999999999999 * 6
という計算式を実行して、 a の値を確認すると、 6 になってしまいます。
(本来 5.999999999999999994 のはず)
Math.random() は 0 以上 1 未満(0 は含むが 1 は含まない)の浮動小数点の疑似乱数を返却する関数ですので、
この丸め誤差の関係で、

コード: 全て選択

(Math.random() * 6) + 25
が 31 になることはあり得るとおもいます。

Math.floor() 関数は、指定された値を超えない、最も近い整数値を返す関数です。
要するに、端数切捨てです。

一般的に、 最小値を Min、最大値を Max として、 Min 以上 Max 以下 の整数値を乱数として得たい場合、

コード: 全て選択

Math.floor(Math.random() * (Max - Min + 1) + Min)
で求めることができます。
この辺りの詳しい解説は、MDN の JavaScript リファレンス の
Math.random() の項目
https://developer.mozilla.org/ja/docs/W ... ath/random
で解説されていますので、一度ご確認ください。
アバター
WTR
記事: 625
登録日時: 2015年12月22日(火) 19:14

Re: (Math.random() * 3) + 1について

投稿記事 by WTR »

ecf5DTTzl6h6lJj02 さんが書きました:この丸め誤差の関係で、
コード: 全て選択

(Math.random() * 6) + 25

が 31 になることはあり得るとおもいます。
なるほど…
そういうコトもあり得るのですね。

ただこの場合ソレが原因かというと…

ちょっと気になったので以下のスクリプトを並列処理で30分ほど回してみてますが一度もヒットしません。
正確ではないにせよ 30min x 60sec x 60frame = 54000回ほどの試行で出ないので
ときどき出ることがある…というのはちょっと考えにくい

コード: 全て選択

const a = Math.random() * 6;
if (a >= 6) console.log("6になった")
追記 1000億回やっても出ませんでした
仕様をちゃんとみればこんな試行回数では試した内に入らないレベルの話でした

なにか勘違いがあるんじゃないかなぁ…
最後に編集したユーザー WTR [ 2021年6月28日(月) 18:07 ], 累計 2 回
Twitter、はじめました。
https://twitter.com/wtr_in_reverie/
nekunyan
記事: 22
登録日時: 2021年5月27日(木) 15:34

Re: (Math.random() * 3) + 1について

投稿記事 by nekunyan »

WTR さんが書きました:
nekunyan さんが書きました:つまり25~30がほとんどだったのが
たまに31になることがありました
そんなはずはないと思いますが…

Math.random() * 6 は最大で0.99... * 6 = 5.99...
これに 25 を足しても 30.99... にしかなりません。切り捨てれば30にしかならないはずです。
やっていることをそのまま全部見せてもらえれば確認できると思います。
変数の操作ではないのですかね?
回答ありがとうございます

やってることはスキルの計算式に入れて
そのスキルを使ったときに


(Math.random() * 6) + 25

つまり25~30がほとんどだったのが
たまに31になることがありました


上記の減少が起きてます

分散も0なので自分にはお手上げ状態です
添付ファイル
計算式.png
計算式.png (17.8 KiB) 閲覧された回数 3306 回
nekunyan
記事: 22
登録日時: 2021年5月27日(木) 15:34

Re: (Math.random() * 3) + 1について

投稿記事 by nekunyan »

ecf5DTTzl6h6lJj02 さんが書きました:こんにちは。
横から失礼します。
nekunyan さんが書きました: (Math.random() * 6) + 25

この式で何度かしていたのですが
基本は上記にある解釈通り

6 + 25 = 31 - 1 = 30

つまり25~30がほとんどだったのが
たまに31になることがありました
恐らく、浮動小数点の丸め誤差によるものです。
コンピュータでは、数値を2進法で表す関係上、小数点をうまく表すことができずに、誤差が生じることがあります。
このため、浮動小数点数を含んだ計算結果が正確な数値にならない可能性があります。
例えば、

コード: 全て選択

a = 0.999999999999999999 * 6
という計算式を実行して、 a の値を確認すると、 6 になってしまいます。
(本来 5.999999999999999994 のはず)
Math.random() は 0 以上 1 未満(0 は含むが 1 は含まない)の浮動小数点の疑似乱数を返却する関数ですので、
この丸め誤差の関係で、

コード: 全て選択

(Math.random() * 6) + 25
が 31 になることはあり得るとおもいます。

Math.floor() 関数は、指定された値を超えない、最も近い整数値を返す関数です。
要するに、端数切捨てです。

一般的に、 最小値を Min、最大値を Max として、 Min 以上 Max 以下 の整数値を乱数として得たい場合、

コード: 全て選択

Math.floor(Math.random() * (Max - Min + 1) + Min)
で求めることができます。
この辺りの詳しい解説は、MDN の JavaScript リファレンス の
Math.random() の項目
https://developer.mozilla.org/ja/docs/W ... ath/random
で解説されていますので、一度ご確認ください。
回答ありがとうございます

察するに
仕様だからそうなってしまうということなんでしょうか?

代わりに

Math.floor(Math.random() * (Max - Min + 1) + Min)

の式を使ってする場合は
誤差に左右されずに最小値と最大値を決めて
その間の乱数を出してくれるということでしょうか?

見た感じだと

Maxに最大値
Minに最小値

を入れればいいのでしょうか?

1~10にしたい場合は

Math.floor(Math.random() * (10 - 1 + 1) + 1)

よろしくお願いします
返信する

“MV:質問”に戻る