• 締切済み

乱数みたいに

1から40までの数を順不同で出したいのです。 RAND関数だと重なりができてしまいますよね。 それなしで、なにかよい関数・方法はございますでしょうか。 かつ、それを40通り作りたいのです。 きっとIF関数とかを使うのでしょうが、私は思い浮かばないのです。 お願いいたします!

みんなの回答

  • shigatsu
  • ベストアンサー率26% (511/1924)
回答No.3

皆さんなぜかCで書かれてますが・・・ココはOfficeシリーズのカテゴリですよね? VBAのサンプルは書きませんが、考え方は配列を使えば何とかなるってことで、他の 方と同じです。 40個の配列を作って、それぞれの要素をランダムに置き換えたり、ソースとなる 配列から乱数で読み出す要素を選んで、必要な40×40の配列に収めるって感じ ですね。前者のほうが楽かな? もう一ひねりして、1つ目の40配列を造ったら、それを2つ目にコピーして再度 ランダムに置き換え、2つ目を3つ目にコピーしてランダムに置き換え・・・ って感じにすれば、ダブることは少ないと思いますね。 置き換えするときも2つの要素番号を乱数で決めたり、置き換える回数を乱数で決 めるとか、色々工夫してみたらいかがでしょう?

  • BigFoot
  • ベストアンサー率31% (16/51)
回答No.2

rand()を使って、重なりを出さずに、1~40の配列を40作る一例です。 この方法は、最初に1~40の数字の配列を作成しておいて、 ランダムにその中から数字を選び、選ばれた数字をその配列から削除し、 残った数字の中からランダムに選び.....を繰り返すやり方です。 ほかにも色々なやり方がありますが、何か参考になれば、幸いです。 char buf[40][40]; char chk[40]; char now[40]; int n, i, k, cnt, rdt; for( n=0; n<40; ){ for( i=0; i<40; i++ ){ chk[i] = i+1; //取り出しテーブルの作成 } for( cnt=0,k=40; k>1; ){ do{ rdt = rand() % k; }while( rdt < 0 ); //取り出し位置の取得 now[cnt++] = chk[rdt]; //選択データの保存 k--; while( rdt < k ){ //選択データを外すループ chk[rdt] = chk[rdt+1]; rdt++; } } for( i=0; i<n; i++ ){ if( memcmp( buf[i], now, 40 ) == 0 ){//作成した配列のチェック break; } } if( i==n ){ memcpy( buf[n], now, 40 ); //乱数配列の登録 n++; } }

  • kaztonao
  • ベストアンサー率0% (0/3)
回答No.1

以下のBoxとMullerの方法(極座標法)はKnuthご推薦である。 #include <stdlib.h> #include <math.h> double gaussrand() { static double V1, V2, S; static int phase = 0; double X; if(phase == 0) { do { double U1 = (double)rand() / RAND_MAX; double U2 = (double)rand() / RAND_MAX; V1 = 2 * U1 - 1; V2 = 2 * U2 - 1; S = V1 * V1 + V2 * V2; } while(S >= 1 || S == 0); X = V1 * sqrt(-2 * log(S) / S); } else X = V2 * sqrt(-2 * log(S) / S); phase = 1 - phase; return X; }

関連するQ&A