【PHP】質問スレッドpart32【php】
■ このスレッドは過去ログ倉庫に格納されています
0001nobodyさん
2006/01/03(火) 17:18:20ID:???【基本ルール】
・新規質問の方は上げてください。age進行でお願いします。
・質問者は2回目以降、最初のレス番号を名前欄に入れてください。
・回答者は質問者に対して>>(アンカー)をつけてください。
・煽り・荒らしは放置。荒らしに反応した香具師も荒(ry
・解決しなくてもこたえてもらったら礼を。
【質問テンプレ】
・マニュアルを調べたか、google検索したか(調べたキーワード)
・タイトル(禁:教えてください!etc) 例:requireとinclude
・内容 例:requireとincludeはどう違うのですか?
・質問する際には環境も明記。
【その他諸注意】
・正規表現・PEAR・テンプレート(Smarty等)・フレームワークはそれぞれの該当スレへ
・SQLについての質問はデータベース板(PCカテゴリ)の各スレで
・オブジェクト指向については良スレがないから本を買え
・速さについては自分でベンチをとってここに書け(違う環境の人も調べてくれるかも)
【PHP マニュアル】
http://www.php.net/manual/ja/
※マニュアル上部の「search for」から検索を活用すべし(便利)。
過去スレ、関連リンク、FAQ等>>2-10辺り
0654nobodyさん
2006/02/06(月) 06:56:04ID:???mt_srand (microtime()*100000);
$rand = mt_rand (0,9999); ですよね?
これを改造して、ある任意の数字だけを選ばれないようにしたいのですが、どうしたらいいでしょう?
たとえば、523と6982と7025だけはランダム結果に含めたくないとします。
このとき、「選ばれたくない数字」が固定かつ少数なら、配列に入れて$randと比較し、含まれてたら
whileなどで再度1行目からやり直せばいいのですが、この「選ばれたくない数字」が多数かつ随時増えていく、としたら
どう対策したらいいか分かりません。もし全部配列に入れていったら、下手したらカブらない数字が出るまで
何千回もループしちゃうわけで・・・。うまいやり方ないでしょうか?
※ちなみにこの「選ばれたくない数字」は実際にはDBに入れてあります。
0655nobodyさん
2006/02/06(月) 06:57:12ID:???0656nobodyさん
2006/02/06(月) 08:48:42ID:???<?php
$array1 = array(10, 15, 6); //選ばれない数字の配列
$array2 = range(0, 9999); //全ての数字の配列
$array3 = array_diff($array2, $array1); //選ばれる数字のみの配列
$rand = $array3[array_rand($array3)];
echo $rand;
?>
0657nobodyさん
2006/02/06(月) 08:51:21ID:???$rand = $array3[array_rand($array3)];
は
$rand = array_rand($array3);
でも同じだった。
0658nobodyさん
2006/02/06(月) 10:17:49ID:???すいません、「神」と呼んでいいでしょうか??
ただ一つ疑問が。。。
手元にある大垣ポケリファ旧版には、「array_rand」という関数が載ってません。
これはバージョン依存の関数ですか??
0659nobodyさん
2006/02/06(月) 10:31:12ID:FPpXqvwharray_randはPHP4からなのでPHP3では使えません。
0660nobodyさん
2006/02/06(月) 10:51:46ID:???0661nobodyさん
2006/02/06(月) 11:09:49ID:???0662nobodyさん
2006/02/06(月) 11:16:25ID:???0663nobodyさん
2006/02/06(月) 11:36:07ID:???0664nobodyさん
2006/02/06(月) 11:37:05ID:FPpXqvwh引数確認したいときとかエディタ上でダブルクリックしてF2キーでも呼び出せるし(PHP editor)。
0665nobodyさん
2006/02/06(月) 11:52:00ID:???配列に1万個も値を入れたら、動作に支障出るよね??
っていうか、配列の限界ってどれくらいなんだろう・・・。
0666nobodyさん
2006/02/06(月) 12:13:47ID:???個数自体はPHPが変数で使用可能なメモリの限界量まで。php.iniで設定。
数値indexとしてはPHPの扱える整数の限界まで。つまり「全ての数字」の配列と同等。
0667nobodyさん
2006/02/06(月) 12:16:57ID:???0668nobodyさん
2006/02/06(月) 12:43:58ID:???3万個とかになってくると実行時間が秒単位になってくるので体感的にかなり厳しい感じ。
0669nobodyさん
2006/02/06(月) 13:09:27ID:???0670nobodyさん
2006/02/06(月) 15:18:39ID:???0671nobodyさん
2006/02/06(月) 18:26:22ID:???euc-jpとか出ないのですが、
これは何が問題でしょうか?
mysqlのujisサポートでインスコとかも繰り返しましたが、
以前症状は変わりません。
0674nobodyさん
2006/02/06(月) 19:03:35ID:???そうだよね??
となると、>>654のやりたいことを解決するには、
>>656以外の方法も考えねばならんか。。。
たとえばこれが1万個じゃなくて100万個だったら、みんなはどう解決する?
配列じゃ現実的に無理だよね。DB内で何かしなきゃならんかな・・??
0677nobodyさん
2006/02/06(月) 19:30:31ID:???ていうか、そんな物をPHPで作らないといけなくなる状況が想像出来ない。
逆に言うと、そんな事やらないといけなくなるのは設計ミスじゃないのか?
0678nobodyさん
2006/02/06(月) 19:42:49ID:???どんな処理でも無制限にデータ量を増やそうとすれば破綻する。
逆にどんな量でも通用する仕組みを作ると今度は小さいデータのときに無駄なオーバーヘッドを生む。
あらゆる条件で通用するロジックなんて無いだろ。
自分の目的に合わせてTPOで選べないやつは単なるコーダーであって設計者とは呼べない。
0679nobodyさん
2006/02/06(月) 19:43:25ID:???んんん???
要するに>>654は「『選ばれたくない数字』が多数かつ随時増えていく」ってのがキモでしょ、多分。
となると、この、どんどん増えていく「除外すべき数字のリスト」に含まれる数字を、
どうやってランダム関数の結果から排除するか・・・っていうアルゴリズムが難しいな。
0〜1万程度なら>>656のやり方でいいだろうが、もし0〜100万の範囲となると・・・
0680nobodyさん
2006/02/06(月) 19:45:38ID:???そうだね。
じゃあ1万個程度の解決策は>>656方式でとりあえずOKとして、
じゃあ100万個レベルだったら、>>679はどうする??
設計者様ならではの思考を知りたいです。
0682678じゃないけど
2006/02/06(月) 19:57:41ID:???設計者様(藁といたしましては、範囲を区分するかね。
例えば100万だったら1万×100ブロックとして処理するとか。
0683nobodyさん
2006/02/06(月) 20:16:50ID:???その範囲の区分の仕方が難しいよね。
たとえば、「除外数字リスト」には次にどんな数字が追加されるのか
予想できれば簡単だろうけど、もしそれもランダムに増えるんだとしたら・・・
0684nobodyさん
2006/02/06(月) 20:18:12ID:???違う違う。
PHPスクリプト内でランダムに計算結果をリアルタイムで求めるんだろうから。
DBにあらかじめ何かが入ってるわけじゃなくて。
0685nobodyさん
2006/02/06(月) 20:29:46ID:???全数字を入れたテーブルをnums、除外したい数字を入れたテーブルをextとして
select num, random() as idx from nums where num not in ( select num from ext ) order by idx limit 1;
みたいな感じでいけるんじゃないの。試してないけど。
0686682
2006/02/06(月) 20:32:38ID:???自分が仕様を理解してないのかも知れんが、
最初にどのブロックで処理をするかランダムに決定して
後はその対象となるブロックの範囲で処理するだけだよ。
当然「除外数字リスト」とやらもブロック毎に分ける。
0687nobodyさん
2006/02/06(月) 21:44:29ID:???除外値が動的に実行時に決まる、とは書いていない。
674で、DB使ったらどうなるかなと聞いてるから答えてるんでしょ。
ていうか654に選ばれたくない数字はDBに入ってるって書いてるし。
0688nobodyさん
2006/02/06(月) 21:50:12ID:???仮に動的に実行時に決まるのだとしてもDBのワークテーブルに一時的に格納すれば済む話。
オーバーヘッドの多い処理方法だが件数が極めて多いときにはそういった手法も有効。
0689nobodyさん
2006/02/06(月) 22:19:50ID:???2
3
4
5
略
とデータがあるのを一個ランダムで消して保存
1
2
3
5
略
となる。次はまた一個ランダムで消す。それを繰り返すだけのことでは?
0691nobodyさん
2006/02/06(月) 23:33:22ID:+hyQlmQi例えば、Aというファイルにfunctionを100個定義します。
そしてBのファイルにAファイルをincludeします。
でも、BのファイルではAのファイルのfunctionのうち、1つしか呼び出しませんでした。
このとき、�@BファイルはAファイルのファンクションを全て読み込むのでしょうか?
�ABファイルはAファイルで使用したファンクションのみを読み込むのでしょうか?
(�@でしたら便利だと思うのですが�Aの状態だと重くなってしまいますよね。)
宜しくお願いします。
0692nobodyさん
2006/02/06(月) 23:49:13ID:???0693nobodyさん
2006/02/07(火) 00:10:46ID:9eIIutOUどれ位の数のファンクション読み込んでもストレスを与えない程度に大丈夫なんでしょうかね。
0694nobodyさん
2006/02/07(火) 00:20:26ID:???APCとかのコードキャッシュを行うアクセラレータを組み込んでればさほど問題ないけど
何も入れてないノーマルの環境だと体感できるほど遅くなってくる場合がある。
程度は関数の数よりコードの分量と複雑さによってくると思う。
200〜300行/20KB程度のclass定義ファイルを10個くらい読み込ませると
サーバー環境にもよるだろうけど0.3秒ほどの遅延が確認できた。
「ストレスを与えない程度」は状況や規模によりけりなので自分で判断しる。
0695nobodyさん
2006/02/07(火) 00:24:53ID:9eIIutOUご親切にありがとうございます。具体的な数字を教えて頂いて助かりました。
300行を2つくらい読み込ませようと思ってたところなんで、ガンガンFUNCを作って
プログラムやってきたいと思います^^
0696nobodyさん
2006/02/07(火) 00:25:10ID:VahS1T1Xその遅延はアクセレータなしの時?
0698nobodyさん
2006/02/07(火) 01:35:51ID:???えぇぇぇぇ
0699nobodyさん
2006/02/07(火) 01:38:21ID:vK7c16Ac<?
function kansai($text){
$text=str_replace("ありがとうございました","おおきに",$text);
}
?>
上記の内容のosaka.incというファイルを作成し
外部ファイルからosaka.incをrequire_once print(kansai($text)) とやると 中に入っていたはずの文字列が全て消えてしまいます。
どこがおかしいのでしょうか?使う関数が間違っているのでしょうか?
0700nobodyさん
2006/02/07(火) 01:41:09ID:???PHPは同種のスクリプト言語の中じゃ特に遅い部類なんだから
速度を気にする香具師はアクセラレータ入れて動かしな
0702nobodyさん
2006/02/07(火) 01:49:18ID:???同種のスクリプトが何を指すかわからないけど、
そこそこ早いと思うぞ。
少なくともrubyよりは早い気がする(検証はしてない)
0703nobodyさん
2006/02/07(火) 01:56:01ID:???0705654
2006/02/07(火) 03:42:33ID:???皆さんありがとうございます。とても参考になります。
>>687さん、私の言葉が足りませんでしたが、除外数字は動的に決まります。
具体的に言うと、ランダム関数で出た数字を一つ一つ「除外リスト」に追加していき、それをDBに保存します。
つまり、0〜10000までの範囲でそのスクリプトを1万回実行すると、最終的には除外リストに1万個の数字が入り、
もう選べる数字がなくなる・・・という風にしたいのです、
(逆に言えば、1万回のランダム計算で、常に一意の数字を選び出したい、ということなんです)
0706654
2006/02/07(火) 03:48:13ID:???「常に一意の数字を」ではちょっと言葉が足りないかもしれません。
「常に一意かつ未だ一度も選ばれてない数字を」です。
0707nobodyさん
2006/02/07(火) 03:56:10ID:???用途が分からんから「こうしろ!」って一つに絞るのは不可能だし、それを使って何がしたいのかもワケワカメ。
まさか糞重い処理をアクセス毎にやるとは言わんだろうけど、最初に作ってDBにでも放り込んでおけば?
0708654
2006/02/07(火) 04:02:26ID:???はい、自分の意図した数字(あるいは文字)の範囲内でランダムな値を得たいので、
uniqidでは無理なんです・・・。
用途はいろいろ応用できるかと思いますが、たとえば「宝くじ番号」みたいなのを
ランダムな順番で発行したりとかにも使えますよね。
0709654
2006/02/07(火) 04:09:45ID:???DB内の「除外リスト(最初は空)」に問い合わせて、該当するものが含まれてなければ
それをリストに追加保存し、該当するものが既にあったら、再度ランダム計算をやり直す…というものでした。
この方式だと、リスト内の数字の数が少ないうちはいいのですが、
だんだん増えてくると数字がカブってランダム計算を何度もやり直してしまう確率が
どんどん上がってしまいまして・・・。
これを解決するのに、数字の範囲が〜10000程度なら>>656さん方式でいいのですが、
100万などとなるとやはり区分けが必要で、その区分けの仕方がうまいこと考えつかなくて・・・
0710nobodyさん
2006/02/07(火) 04:34:05ID:???リクエストごとにリストを作り直すような使い方には極めて不向きだけど、
結果をDBなりファイルなりに保存しとくなら許容できるっしょ。
<?php
$a = range(0, 999999);
var_dump(number_format(memory_get_usage()));
shuffle($a);
$b = array_slice($a, 0, 100);
unset($a);
var_dump(number_format(memory_get_usage()));
$c = array_map(create_function('$n', 'return sprintf("%06d", $n);'), $b);
print_r($c);
?>
string(10) "60,238,624"
string(6) "64,848"
Array
(
[0] => 354393
[1] => 080271
(中略)
[98] => 030508
[99] => 717038
)
0711nobodyさん
2006/02/07(火) 04:46:21ID:???宝くじ番号をランダムに発行する必要性がないからな・・やっぱり何を作ってるのか分からない・・・。
上位桁(0〜1000)と下位桁(0〜999)に分けて、
・上位桁の既出リストをDBから取得
・それを元にランダムに一つ選ぶ
・結果から下位桁の既出リストを取得
・それを元に(ry
上位桁*1000+下位桁=ランダムな値
(もしやるなら上・中・下位桁の3段ぐらい欲しいな。)
0712nobodyさん
2006/02/07(火) 04:47:40ID:???$min = 0;
$max = 999999;
$num = 100;
$fmt = sprintf("%%0%ds\n", strlen(strval($max))); // パディングは好みで
$list = array_rand(range($min, $max), $num);
shuffle($list);
foreach ($list as $n) {
printf($fmt, $n);
}
0713nobodyさん
2006/02/07(火) 12:56:49ID:???リクエストごとに頭から順に返していって「ここまで使用済み」というカウントだけ保持しときゃいいと思う。
これが1番お手軽かつ高速。
0714713
2006/02/07(火) 13:00:06ID:???リクエストごとに1個削除してそれを返していく方式とか。これならカウンタの保持も要らない。
なんにせよ、そんな案件をリアルタイムにデータ生成してるのはただのバカかと。
0715nobodyさん
2006/02/07(火) 13:09:10ID:???0716nobodyさん
2006/02/07(火) 13:48:49ID:???たしかにそれはいいね。
でも数字だけならそれでいけるけど、これがさらに「a5fw8g」みたいに、
任意の英数字で構成される文字列が対象だと、その手法も使えないよな。
こういう予測が不可能(または無限に近い)な文字列だったら、どうする?
やっぱリアルタイム生成でうまい方法を考えるしかないっしょ・・・
0717nobodyさん
2006/02/07(火) 14:05:22ID:???それならsubstr+md5+uniqidする
かぶる可能性はかなり低くなるのでDBへの問い合わせもそんなにループしないと思う
0718nobodyさん
2006/02/07(火) 14:14:03ID:???ん? それでも「使用候補リスト」をあらかじめ作っておく方式にするの!?
いったい何百万個用意しておく気だい・・・??
しかしこのスレ、みんなのいろんなアルゴリズムが見れて楽しいなw
0719nobodyさん
2006/02/07(火) 14:17:35ID:???バイナリファイルを読み込んで内容を16進で出力したいんですが、
どのように出力すればいいのでしょうか?
fget()で読み込んでそのままprintしただけでは
当然文字として出力されてしまいます..。
そもそも読み込み方が違うのでしょうか?
宜しくお願いします。
0720nobodyさん
2006/02/07(火) 14:23:56ID:???echo bin2hex(fgetc($fp))
桁もそろえたいなら
printf("%02X", ord(fgetc($fp)))
あたりでドゾ
0721nobodyさん
2006/02/07(火) 14:25:10ID:???自分で何を言っているのか判ってないんだろうから解説するとね。
●数学的に完全にランダム。(過去の記憶を持たない:重要)
●過去に出た文字列は出さない(過去の記憶が必要:重要)
つまりね、命題として、”リアルタイム生成”ってのは既に不可能なんだな。
なんらかの形で過去を記憶しなきゃならん。
でだ実際に君が欲しがっているものは、実は真にランダムな文字列の列じゃなくてね
n文字の組み合わせからm個とる順列のうちの一つだがね。
結論としてね、n文字の組み合わせを生成するのと、m個の順列を生成する際の
オーダーによってアルゴリズム変えなきゃならないわけ。
下らない質問か、アルゴリズムスレ(そんなの有るのか?)向けの話だと思うけどね。
0722nobodyさん
2006/02/07(火) 14:26:21ID:???それ、可能なパターンをあらかじめ全種類作る必要無いでしょ。
その文字列リストを何の目的で使うのかによるんだけど、
宝くじとかで最終的なユーザ数(リクエスト数)が想定できるなら、
使う可能性のある分だけランダムに生成した文字列をあらかじめ入れとけばいいだけでしょ。
また、これを何十年も運用し続けるというのであれば、初回に100万種類用意しといて動かし、
そのプールが尽きたら、過去の100万と被らない次の100万種類を新しいテーブルに生成。
その繰り返しで文字列生成の限界まで運用すればいいと思う。
これでもデータ生成は継続時にバックグラウンドで1回だけ行うだけだから、
それ以外の通常運用時の負荷は非常に低い。
何の問題も無いと思うが?
0724nobodyさん
2006/02/07(火) 14:30:27ID:???最終的には「使用候補リスト」→「使用済みリスト」に
置き換わって行くわけだから別に最初からリストアップしてても問題はないんじゃない?
だって運用していけば、その何百万個が入った「使用済みリスト」が出来ることは
仕様に盛り込まれてるんでしょ。
0725nobodyさん
2006/02/07(火) 14:39:40ID:???使っていない数字数百万をどっかに保存するのと
使った数字数百万をどっかに保存するのとなら、
最大に使う容量は最終的には変わらん。
宝くじは適当な番号を生成してるんじゃなくて、
連番で作ったくじをバラバラに配っただけ。
そもそも8桁(一億程度)の数字の中で数万しか使わないのなら
適当に数字を選んで、使っていたら選びなおすというアルゴリズムでも
発生に要する時間を気にする必要も無いかと。この場合、
すでに使った数字にぶち当たる確率は最も高くて1000分の1だから、
数値を3回選ぶ必要がある事すら数回あるか無いか、な訳で・・・。
0000〜9999の数値が全くかぶらずに適当に1万種(つまり全部)出てくるのなら前者、
00000000〜99999999の数値が全くかぶらずに適当に10万種出てくるのなら後者
0726nobodyさん
2006/02/07(火) 15:07:45ID:???>命題として、”リアルタイム生成”ってのは既に不可能
言っている意味が分からないなぁ。
既出の数字を避けつつリアルタイム生成・・・って可能でしょ。
>>724
「使用候補リスト」と「使用済みリスト」はお互いにカブらないものだから、
どちらか一つあれば十分だよね。
当初は「使用済みリスト」しか考えつかなかったから、それが仕様になってたんじゃない?
>>725
宝くじってのはあくまでも一例でしょう。
俺もこの系統でいろいろ用途は思いつくぞ。
0727nobodyさん
2006/02/07(火) 15:17:16ID:???わからない?
これ”ランダム”な文字列の生成だと思ってるみたいだけど、実際には”シャッフル”の問題だと言う事。
リアルタイム生成(いまいち実体は掴めないが)に必要な条件は”過去を無視”できると言う事。
だから”ほぼ”過去を無視できるなら(つまりm個)が小さいなら、擬似的に”リアルタイム生成”
も可能だが、そうではないなら厳しいと言う話。
どこで区切るかは、それこそオーダーの話になってくるよ。
という事なんだけど、判ってもらえるかな?
0728nobodyさん
2006/02/07(火) 15:18:41ID:???>>721は「リアルタイム生成」=「一切の元情報なしでその場で算出」と勘違いしてるだけかと。
>>725の話は一例だとして、事前に必要数をプール→足りなくなったら補充方式でダメなケースって何?
いずれにせよ、アルゴリズムは用途に応じて最適なものを選択するものなんだから、宝くじって言われたら
それに適した解を出すべきであって、そこに無理に抽象化されたアルゴリズムを持ち出すのは無意味かと。
この方法では問題のあるケースに適したアルゴリズムを出せというなら、まずその用途を出しましょう。
0730nobodyさん
2006/02/07(火) 15:45:38ID:???まぁ、やっぱり何に使うのか分からんわけで
>>726
それって絶対この重い処理が必要なのか、無理に使うなら山ほど浮かぶけど絶対に必要ってのは余程条件に縛りを入れないと・・
0731nobodyさん
2006/02/07(火) 15:48:55ID:???> Cか何かで既出(or未出)を保持するの作って、そいつと通信
それで1番手っ取り早くて確実なのがRDBなんじゃないの?
既出分はどんどん追加登録されていくわけで、それに対するロックとかも考えると中身はまるっきりDBだし。
0732nobodyさん
2006/02/07(火) 15:57:10ID:???>>728
まあとりあえず想定できるケースとしては、数字の範囲が0から1万までの場合(少ない)と、
0から100万までの場合(多い)と、英字も混じるケース(多い上にランダム性が増す)の
3パターンに分けて考えるといいのでは。。。
0738nobodyさん
2006/02/07(火) 17:10:44ID:???基本的に抽出元リストと除外リストがオンメモリで扱える分量かどうかの2パターンしか無い。
全部数字なのか文字を含むのかはまったくどうでもいい話。
0739nobodyさん
2006/02/07(火) 17:15:24ID:???宝くじの例をわざわざ引っ張り出してきたのは、使い道の一例というより
アルゴリズムの思案方法が間違っている(逆)ことを指摘したかっただけ。
「すでにある数字を避けつつ選んだ適当な数値」を「宝くじに使う」と
言い出したので、その説明を出したまでのこと。
0741nobodyさん
2006/02/07(火) 17:58:46ID:???どっちかというとくだ質は、一問一答で
軽やかに流れる質問のやりとりが身上だから。
くだらないというよりも、なさけない質問も多いが。
0742nobodyさん
2006/02/07(火) 18:02:06ID:???0745nobodyさん
2006/02/07(火) 19:32:54ID:???0746nobodyさん
2006/02/08(水) 09:10:00ID:???0747nobodyさん
2006/02/08(水) 12:35:12ID:???$hoge =& new xxxx();
としてあるのですが
この 「=&」 はどんな意味があるのでしょうか?
単に「=」とするのとは違うのでしょうか?
0748nobodyさん
2006/02/08(水) 12:37:10ID:???マニュアル嫁
http://www.php.net/manual/ja/
0750nobodyさん
2006/02/08(水) 13:50:07ID:???ここに答えがそのまま書いてあるのだー
http://www.php.net/references.whatdo
0751nobodyさん
2006/02/08(水) 19:14:53ID:???クラス内では宣言できないですか?
■ このスレッドは過去ログ倉庫に格納されています