HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2016
1221
赤松乱数をもとに文字列を生成したい9解決


赤松

リンク

2016/12/21(Wed) 17:16:40|NO.77673

以前も教えていただきましたがまたお世話になります。
今HSPとは関係のないことでGUIDを頻繁に使うので、GUIDジェネレーターのようなスクリプトを作りました。
rand関数で得られた数を元に文字列を作るだけの簡単なもので、完成したのですが、動かすと

6888ffd7cbcfac888ee333eaefffbbbb 6888ffd7-cbcf-ac88-8ee3-33eaefffbbbb
のように出る文字が偏ることがよくあります。
試しに

randomize repeat 100000 random = rnd(2) if random = 1:kekka.1+ if random = 0:kekka.0+ loop mes ""+kekka.1+"\n"+kekka.0
などしてみると問題ないので文字にする部分の問題かと思い試行錯誤してみましたが原因がわかりませんでした。
GUIDとして使うには大きな問題はないのですが原因が知りたいので質問させていただきます。
汚い書き方で申し訳ないですが原因がわかる方教えていただけますか。

スクリプト:

randomize GUID="" mesbox GUID,500,40,0 objid.1 = stat objsize 200,30 button "GUID Generate" , *NewGUID *NewGUID//GUID生成 sdim GUID,10 moji="" repeat 32 if rnd(25) < 10{ mojiid = rnd(10)+48}else{//数字 mojiid = rnd(6)+97}//アルファベット poke moji,0,mojiid GUID.0 = GUID.0+moji if cnt=8|cnt=12|cnt=16|cnt=20:GUID.1 = GUID.1+"-"+moji if cnt!8&cnt!12&cnt!16&cnt!20:GUID.1 = GUID.1+moji loop GUID.2 = GUID.0+"\n"+GUID.1 objprm objid.1,GUID.2



この記事に返信する


InoueSoftware

リンク

2016/12/21(Wed) 17:48:28|NO.77674

数字とアルファベットを分けるのではなく一気にやった方が良い。
strfという命令を使って16進数などに変換をすることが出来る。

randomize GUID="" mesbox GUID,500,40,0 objid.1 = stat objsize 200,30 button "GUID Generate" , *NewGUID *NewGUID//GUID生成 sdim GUID,36,2 //XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXXの形式にする //0xFFFFの範囲で乱数作成。書式変換で16進数にする GUID(0)=strf("%X%X-%X-%X-%X-%X%X%X",rnd(0xFFFF),rnd(0xFFFF),rnd(0xFFFF),rnd(0xFFFF),rnd(0xFFFF),rnd(0xFFFF),rnd(0xFFFF),rnd(0xFFFF)) GUID(1)=strf("%X%X%X%X%X%X%X%X",rnd(0xFFFF),rnd(0xFFFF),rnd(0xFFFF),rnd(0xFFFF),rnd(0xFFFF),rnd(0xFFFF),rnd(0xFFFF),rnd(0xFFFF)) objprm objid.0,GUID(0)+"\n"+GUID(1)



InoueSoftware

リンク

2016/12/21(Wed) 17:50:51|NO.77675

原因は数字とアルファベットの境を乱数で分けている点と、一字ずつ乱数を作成している点。



スペース

リンク

2016/12/21(Wed) 17:52:20|NO.77676


if rnd(25) < 10{
この部分、25回中10回は数字、15回はアルファベットに分岐しますよね。
そしてアルファベットの処理で

rnd(6)+97
となっています。
これではa、b、c、d、e、fの6種類しか出現しない為、数字に比べて連続する確率が遥かに高くなります。
正しくは数字10種類、アルファベット26種類、合わせて36なのでrnd(25)を25から36にして、
rnd(6)+97の部分を6から26にする必要があるのではないでしょうか。



スペース

リンク

2016/12/21(Wed) 18:05:58|NO.77677

追記。
もしかして、この文字列は16進でしょうか?
だとしたらrnd(6)+97はそのままに、

if rnd(25) < 10{
の25を16にすれば文字被りは解決するかと。



KA

リンク

2016/12/21(Wed) 18:16:02|NO.77678

16進表記で8−4−4−4−12の形にするのかな?
数値として0から15の範囲で乱数を発生させた方が良い気がします。



MillkeySoftware

リンク

2016/12/21(Wed) 18:24:43|NO.77679

rnd(25) の時点で、おかしいよね・・・
抽選文字列は、"0"〜"9" と "A"〜"F" なのだから、16種類。

16種類なのに、25種類の抽選を行い、結果を表示している。
数字 10種類に対して、アルファベット 15種類として行っているよね?
アルファベット当選が大きすぎる。その為、約 1/3 の確率で重なりが発生してしまう。

単純に 16種類なら 16種類の中から抽選した方が偏りが発生しないと思うよ。

GUID="" mesbox GUID,500,40,0 objid.1 = stat objsize 200,30 button "GUID Generate" , *NewGUID *NewGUID//GUID生成 randomize sdim GUID,10 rnd_moji="0123456789abcdef" moji="" repeat 32 mojiid = rnd(16) poke moji,0,peek(rnd_moji,mojiid) GUID.0 = GUID.0+moji if cnt=8|cnt=12|cnt=16|cnt=20:GUID.1 = GUID.1+"-"+moji if cnt!8&cnt!12&cnt!16&cnt!20:GUID.1 = GUID.1+moji loop GUID.2 = GUID.0+"\n"+GUID.1 objprm objid.1,GUID.2



赤松

リンク

2016/12/21(Wed) 18:51:04|NO.77681

スペース様ありがとうございます。

if rnd(25) < 10{
では確立がおかしくなりますね、うっかり気づきませんでした。
ここを直せば数字とアルファベットの確立が自然になり、思い通りの動作になりました。

InoueSoftware様ありがとうございます。
いくつか理解できない箇所がありますが、最初に考えた方法とほぼ同じでした。
しかしハイフン有り無しで同じ内容でないといけないため最初に断念しました。
しかも実行した結果桁数が7-4-4-4-11や8-4-3-4-12など、
8-4-4-4-12に満たないことがあったりして使えなかったです。

最終的にスペース様、MillkeySoftware様に指摘していただいたrnd(25)⇒rnd(16)で解決しました。
ちなみにrnd(25)は完全にミスです。よく見直せばよかったですね、申し訳ありません。
ありがとうございました。



赤松

リンク

2016/12/21(Wed) 20:10:25|NO.77682

解決のチェックを付け忘れていましたので付けます。
質問に答えてくださった皆様ありがとうございました。



inovia

リンク

2016/12/25(Sun) 01:57:06|NO.77714

解決したようですが、一応補足的に。

GUID(UUID)は生成アルゴリズムが決まっているので、
今回みたいですべて乱数で作成したGUIDだと用途によってはトラブルの元になるかもしれません。
(乱数だけで作っちゃうと、ユニークにならない可能性がありますし)

UUID version1の生成アルゴリズム
http://qiita.com/takc923/items/b5ff68c7ac272c18fe89

UUID - Wikipedia
https://ja.wikipedia.org/wiki/UUID

WindowsだったらGUIDを生成してくるAPIがあるので、
用途によってはそちらのほうが良いかと思います。

UUID生成
http://quasiquote.org/hspwiki/UUID%E7%94%9F%E6%88%90



ONION software Copyright 1997-2023(c) All rights reserved.