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

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

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

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

2回答

1275閲覧

英数字のランダムな文字列を生成したい

omochidayo

総合スコア3

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

0クリップ

投稿2021/07/14 10:38

編集2021/07/14 12:21

前提・実現したいこと

PHPで$a(8桁から19桁の数字)と$b(2桁以下の数字)のパラメーターを使用して、7桁の英数字のランダムな文字列を生成したいです。
元々$aの値が最大9桁の数字で、以下のプログラムでできていたのですが、最大19桁に増えてしまったため、同じ文字列が生成されるようになってしまいました。

みなさまのご回答から7桁では無理だということが分かったので12桁に増やすことを検討中です。
その場合のシードの設定方法で良い案があればご教授ねがいます。

追記
$a apiから取得しているユーザーごとに違う数値
$b 使った日数
になります。

発生している問題

srand((float)$a* 10000 + $b);

桁数が大きくなってしまった時、↑の部分により種が同じになってしまっているのが問題なのは分かるのですが、いい解決方法が思い浮かびません…
何か良い方法があればご教授願います。

修正したソースコード

//$aは8桁から19桁の数字。 //$bは2桁以下の数字。 //数値のexample $a =99999999; //うまくいっていた $a =9999999999999999999; //桁数が増えたことによりうまくいかない $b =23; //2桁以下の数字 srand((float)$a* 10000 + $b); $val = ''; for ($i = 0; $i <= 11; $i++) { $rnd = rand(0, 61); if ($rnd <= 9) { $rnd += 48; } else if($rnd <= 35) { $rnd += 55; } else { $rnd += 61; } $val .= chr($rnd); } return $val; var_dump($val);

追記

ご回答ありがとうございます。
今のままでは難しいことが分かり英数字を7桁から12桁に増やすことにしました。
それからその場合シードをどう設定したら良いと思いますか。
本当に初心者で全然分かっておらずすみません。

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

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

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

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

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

itagagaki

2021/07/14 10:58

srand((float)$a* 10000 + $b); 引数の意味がどうにも理解できないので解説してもらえますか?
omochidayo

2021/07/14 11:12 編集

すみません。 元々自分の書いたコードでなく引き継いだものなので、よく分かりません。 以前は$aが8桁以下の数値だったので、10000倍して、$bを足して、種が重複しない別の数値になるようにしていたのかなと思います。 ちなみに$aに当たる部分は、各ユーザーに割り当てられた番号、$bは使った日数になります。
guest

回答2

0

ベストアンサー

そもそも、

7桁のランダムな英数字は、
a-z 26個
0-9 10個
→36個の文字から任意の7個を抽出した「順列」の数
42,072,307,200通り

A-Z 26個を加えても、
→62個の文字から任意の7個を抽出した順列の数
2,478,652,606,080通り

でしかありません。

19桁の数字×2桁の数字では、
9,999,999,999,999,999,999×99=989,999,999,999,999,999,901通りの順列がないと重複は避けられないと思うのですが。

($aが99,999,999の場合は99,999,999×99=9,899,999,901でしかないので、a-z 0-9の42,072,307,200通りで十分対応ができます)

(数学自信ないですがたぶん合ってると思います)

$aの19桁と$bの2桁はそれぞれ何由来のもので、最終的な7桁の英数文字列は何に使うつもりなのかを教えて頂ければ現実的な回答ができると思います。

コメントを加味して追記

$bが日付(yyyy-mm-ddのdd)とのことですが、それだと0-31で、月が替われば重複する可能性があります。
(7/14と8/14で同じ値になる)
絶対に重複しないとなると、日付は8桁で表す必要があるので、ユーザー固有の番号が19桁なのであれば19+8=27桁が必要になります。
英数7桁では2,478,652,606,080通りしか表現できないため、到底不可能です。
そもそもユーザー固有の番号に19桁も必要なのか?最終的な答えは7桁ではなくもっと桁数を増やせないのか?そこから検討が必要かと思います。

$bは日付ではなく「使った日数」でしたね。その場合、100日目はどうするのでしょう?考慮不要ですか?
考慮不要と仮定して19+2桁なら21桁、いずれにせよ英数7桁(26+26+10=62進数7桁)では表現しきれないので重複の可能性は排除できません。
62進数12桁まで増やせれば、
999999999999999999999(10進数21桁の最大値)=jdt8BLTpPG02(62進数)なので、単純に10進数→62進数変換で対応できます。

投稿2021/07/14 10:54

編集2021/07/14 11:38
F_I_A

総合スコア104

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

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

omochidayo

2021/07/14 11:08

回答ありがとうございます。 $aに当たる部分は、各ユーザーに割り当てられた番号、$bは使った日数になります。 最終的にできる英数字の文字列は、ある特定日にあるユーザーが作成したものにそれぞれ割り当てられるようにしたいです。 別の日に作成したら別の文字列に…というような感じにできたらと思っています。
F_I_A

2021/07/14 11:17 編集

最終の英数字文字列は、 ・パスワード的に使うのですか?(秘匿性が必要ですか?) ・それとも単にユニークなものであればいいのですか?
omochidayo

2021/07/14 11:14

パスワードのようなものではありません。 ユニークなもので、使った日が変われば別のものに変わるようにしたいです。
F_I_A

2021/07/14 11:17

そもそも各ユーザーに割り当てられた番号(ユーザーID?)って19桁も必要ですか? 世界人口よりだいぶけた違いに多いですけど。。。
omochidayo

2021/07/14 11:24

>そもそも各ユーザーに割り当てられた番号(ユーザーID?) こちらはapiから取得しているものになります><
omochidayo

2021/07/14 12:01

ご回答ありがとうございます。 生成される英数字の桁数を増やす方向で考えます。 ちなみにその場合シードをどう設定するのが良いでしょうか。 $bが100日超えるのは考慮不要で構いません。 度々すみません。もし良い方法があればご教授願います。
F_I_A

2021/07/14 13:32

解決済みにされてしまったので回答が編集できません。 ###### そもそも21桁の10進数は64bit環境でもオーバーフローするため、62進数変換で解決、にはなりませんね(うっかりしてました) 最終的な解が「英数〇桁」に拘らないのであれば、$aと$bを共に文字列として連結した$strに対して、open_sslでencodeで対応します、自分なら。 必要ならdecodeで復号できますし、重複も避けられるはずです。
m.ts10806

2021/07/14 20:39

質問も回答も編集に制限はなかったと思いますが・・。 (もちろん回答ついた後や解決後の編集は気を遣うべきですが)
F_I_A

2021/07/15 01:15

編集中にベストアンサーになったからかな? 最終的な投稿時点で404になりました。
m.ts10806

2021/07/15 01:17

あ、それはあります。 データ時な区分が変わるんでしょうね。
guest

0

疑似乱数の発生系列を、$aと$bの組み合わせごとに異なるものにするのがsrandを使用している目的かと思います。

しかし、srandの引数(seed)はintで、64bitのシステムでも最大9223372036854775807です。
そこのところを考えてseedを選ぶ必要があります。
$aと$bのすべての組み合わせで完全に違うseedを選ぶことは不可能でしょうね。

なお、その引数をfloatにキャストして計算していますが、それはまったくの無駄です。

投稿2021/07/14 11:14

itagagaki

総合スコア8402

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.46%

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

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

質問する

関連した質問