• ベストアンサー

long型のランダムな値を返す方法

C言語について質問させて頂きます。 私は今、0以上50万以下(上限は50万以上ならどんな値でもかまいません)の範囲でランダムに整数を得たいと考えております。 #include <stdlib.h>のint rand(void)は0以上の乱数を返してくれますが、返す値はintの範囲内(?)なので、要望に合っておりません。 そこで、long型のランダムな値を得たいと思っております。 一体、どのような関数またはアルゴリズムを使えば、望むように出来るのでしょうか? 是非、お教えください。

質問者が選んだベストアンサー

  • ベストアンサー
  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.2

手抜きで考えるなら ランタイムのrandが 0から32767までを返すなら randを値を2つ取って一方は4ビットシフトして0x7fff0まで作ります 他方の下位4ビットとの合計をします この値から 希望の50万での剰余を求めるとか long myRand( long limit ) {   long nRes[2];   nRes[0] = rnad() << 4;   nRes[1] = rand();   nRes[0] |= nRes[1] & 0x0F;   return nRes[0] % limit; }

eigasaikou
質問者

お礼

ビット演算を利用するという私にとっては予想外な発想でのアルゴリズムをどうも有り難うございます。いい事を学べました。 このアルゴリズムを使うと100万でも1000万でもいけそうですね。 是非、活用させていただきます。

その他の回答 (8)

  • D-Matsu
  • ベストアンサー率45% (1080/2394)
回答No.9

回答というより補足説明っぽいですが。 昨今のコンパイラではintとlongはたいてい一緒なので、No.1の回答ままでもご期待の動作は得られるかと思います。 が、int型の大きさはコンパイラ依存なのであまり望ましくないのも事実ですね。キャストをlongにしてしまえば確実になります。 なおrand()の返す最大値はlimits.hのRAND_MAXで規定されています。大抵はshort、もしくはunsigned shortの最大値になっているでしょう。

eigasaikou
質問者

お礼

説明を有難うございます。 limits.hをまた調べてみます。

  • titokani
  • ベストアンサー率19% (341/1726)
回答No.8

#7です。訂正 元の値 剰余 0 0 1 1 2 2 3 0 でした。 多くなるのは0の場合ですね。

eigasaikou
質問者

お礼

丁寧な回答を有難うございます。 どの値が出る回数が最も多いかはあまり気にしておりませんが、頻度については確認しておこうと思います。

  • titokani
  • ベストアンサー率19% (341/1726)
回答No.7

>rand()+rand() で、0~2*RAND_MAXまでの値が得られると思います。。 この方法だと、RAND_MAX+1の値が一番多く出ることになってしまいます。 サイコロを2つ振ったときの合計は7が一番多くなるのと一緒ですね。 >この値から 希望の50万での剰余を求めるとか これも微妙に良くないです。 例えば、0~3までの乱数発生器があったとして、0~2までの乱数が欲しい時、3での剰余を使うと 元の値 剰余 0 0 1 1 2 2 3 1 となって、1が出る確率が多くなります。 どうせ手抜きでも、目的の値より大きな値がでたら、もう一回やりなおしのほうがいいかと思います。

  • titokani
  • ベストアンサー率19% (341/1726)
回答No.6

それなりにまともな質の乱数が欲しいのなら、調べれば乱数アルゴリズムはみつかりますから、それに基づいて独自に実装するのがいいと思います。 乱数の質にこだわらないのなら、rand()を2回使えばいいと思います。

回答No.5

rand()+rand() で、0~2*RAND_MAXまでの値が得られると思います。。

eigasaikou
質問者

お礼

小技なアイデアをどうも有り難うございます。 その作戦に気づきませんでした。 早速longの範囲でのランダム値が得られるようにやってみます。

  • koko_u_
  • ベストアンサー率18% (459/2509)
回答No.4

random() とか使えれば、それを利用するのがよい。精度的な意味でも。

  • Tacosan
  • ベストアンサー率23% (3656/15482)
回答No.3

まじめにいくならどこかから Mersenne Twister でもひろってくる.

回答No.1

0~n の乱数 (int)((n + 1) * (rand() / (RAND_MAX + 1.0))

eigasaikou
質問者

お礼

int型では希望の範囲の値が得られないんですけど、、 回答は有難うございます。

関連するQ&A

  • 乱数発生

    #include <stdio.h> #include <stdlib.h> #include <time.h> int main(void) {int y, m, l; srand( (unsigned)time( NULL ) ); y=rand() % 2500 + 1600; m=rand() % 12 + 1; l=rand() % 29 + 1; printf("西暦%d年%d月%d日",y,m,l); return(0); }今回は乱数発生でランダムにだされた西暦年月日をつくりましたが、y=rand() % 2500 + 1600; というのがありこれはyという乱数が2500以下1600以上という意味なのですがなぜかプログラムを実行しても3000いくつとか4000いくつなんてのもでてきます。m=rand() % 12 + 1;はちゃんと12以下1以上でできるのですがなぜですか?本当にわかりません。是非だれか教えてください。

  • 何番目に作成されたのかを表示させる方法

    ある範囲内で整数を複数個、適当につくり、その整数の平均値を取った後、適当に作った整数と最も近い平均値が何番目に作成されたのかを表示させるという問題についての質問です。 とりあえず1から100までの整数、その数10個にして、 #include <stdio.h> #include <stdlib.h> #include <time.h> int main() { int a[9]; int ave; time_t t; int i; int sum; srand(time(&t)); for(i = 0; i < 10; i++){ a[i] = rand() % 100; printf("ransu%d\n", a[i]); } ave += a[i] / 10; printf("ave%d\n", ave); return 0; } と、すればとりあえず乱数10個は生成されたのですが、何故かaveの値が合いません。 あと、この生成された乱数とaveの絶対値の差が最も小さいもの=最も平均値と生成された乱数の値が近い、と言うプログラムを書けば良いのだと思うのですが、その場合、どの様な式を使えば導き出せるのか、教えて頂ければ幸いです。 よろしくお願いいたします。

  • C言語でサイコロのプログラムを作ってみたのですが

    まず、以下のような”実行するたびに1~6の数字をランダムに出力するプログラム”を 作ってみたのですが、特定の数字が出てこないのです。 例えば、1と4、2と5、3と6 が出ない ここで気がついた事は、 1、出ない目の2数の差は3であること。 2、乱数自体を表示させたところ、ちゃんと1秒毎に乱数は変わっている。こちらには問題はない 3、約1分間隔で、出ない数字の組み合わせが変わる。 (例えば 1,3,4,6,1,6,3,6,4(2と5が出ない)  →1分間実行し続けると・・・  2,3,6,5,3,2,2,6(1と4が出ない)) この原因は一体なんなのでしょうか・・・ とても気になって仕方がありません。わかる方教えてください。 以下、ソースコードになります #include<stdio.h> #include<time.h> #include<stdlib.h> int func(void); int main(void){ int number=0; number=func(); //サイコロの目の表示 printf("%d\n",number); return 0; } int func(){ //乱数の初期化 srand((int unsigned)time(NULL)); //サイコロの目をランダムで出力し、返す return rand()%6+1; } プログラムの仕組みは パソコンから現在の歴時刻を元に乱数の初期値を変更 ↓ rand関数で適当な値を受け取り、6で割った余剰+1を計算し値を返却する

  • メルセンヌツイスターによる乱数の使い方

    メルセンヌツイスターによる乱数を生成したいのですが、下記コードにすると、mt_rand関数を呼ぶたびにシードが初期化され他乱数が生成されます。 やりたいことは、main関数で一度シード101で初期化した後は、mt_rand関数内では、初期化することなく継続した乱数を生成したいのです。 そのためa_mt_rand関数のようにすると、mtが定義されていないとなるエラーとなります。 namespaceの問題と思うのですが、色々試してみましたが、できませんでした。 どのようにすればできるでしょうか。 vc++11、windows11 使用 参考サイト C++ 乱数ライブラリ std::random の使い方 リンクはうまく貼れませんでした。 #pragma hdrstop #include <iostream> #include <stdio.h> #include <random> using namespace std; void mt_rand(void); int main(int argc, char *argv[]) { int ptr; std::mt19937 mt(101); // メルセンヌツイスターの32ビット版、引数は初期シード std::uniform_int_distribution <> rand100(0, 100); // [0, 99] 範囲の一様乱数 ptr = rand100(mt); printf("ptr=%d\n",ptr); mt_rand(); } void mt_rand(void) { int ptr=0; std::mt19937 mt(101); // メルセンヌツイスターの32ビット版、引数は初期シード std::uniform_int_distribution <> rand100(0, 100); // [0, 99] 範囲の一様乱数 ptr = rand100(mt); printf("%d\n",ptr); } void a_mt_rand(void) { int ptr=0; ptr = rand100(mt); printf("%d\n",ptr); }

  • 整数のランダム生成について

    エクセル98を使用しています。 例えば1~5の数字の整数をランダムに発生させようとしているのですが、 =INT(RAND()*5+1) と記述する方法と =INT(RAND()*5)+1 と記述する方法があるのですが、どちらが良いのでしょう? 実際試したみたところ、どちらも1~5の整数をランダムに発生させることができています。 結局は同じ意味なのでしょうか? 大したことではないのですが、よろしくお願いします。

  • 数当てゲームを作っているのですが

    数当てゲームを作っているのですが 乱数を設定してその値よりも小さい値を入力したら「小さい」、 大きい値を入力したら「大きい」と表示して その値を入力したときは「正解」と表示するような数当てゲームを作っています。 一応コードは書けたのですが、コンパイル、実行がうまくいかないのです。 ご指摘お願いします。 以下コード /* 1~99の乱数を発生させる */ #include <stdio.h> #include <stdlib.h> #include <time.h> int main(void) { int i,random; // 乱数の種を植える,種に時間を使う srand((unsigned)time(NULL)); for(i=0; i<1; i++) { //乱数の発生 random = 1 + rand()%99; printf("%d\n",random); } printf("数当てゲームをはじめます。\nコンピュータが当たり数を用意しました。当たり数は1~99の間にあります。\n"); for(;;) { printf("あなたの予想は? > "); scanf("%d",&i); if(i>random) puts("大きい"); else puts("小さい"); break; } if(random - i = 0) printf("正解"); return (0); }

  • extern指定子の使い方

    こんにちは。 現在WindowsVistaでCプログラミングを行っています。 独習Cという本に沿って勉強しているのですが、extern指定子の使い方の所でつまずきました。 まず、サンプルプログラムを参照し、以下のような2つのファイルを作成しました。 (必要なヘッダファイルは全てインクルードしています。) ●main.c ____________________________________________________________ extern int random; void func(void); void main(void) { int i; for(i=1; i<=10; i++){ func(); printf("発生した乱数 : %d\n", random); } } ____________________________________________________________ ●func.c ____________________________________________________________ int random; void func(void) { long ltime; long utime; /*まず、time()関数とsrand()関数を使って乱数列の初期値を 毎回変更できるようにする*/ ltime=time(NULL); utime=(unsigned int)ltime/2; srand(utime); //乱数を発生させてrandomに代入する random=rand(); } ____________________________________________________________ この2つのファイルをコンパイルし、実行した所同じ整数が10個表示されました。 異なる整数を10個表示したいのですが、どうすればよいかが分からず困っています。 何か分かる方がいらっしゃれば、アドバイスをお願い致します。

  • 意味がわかりません

    1から10のうちで乱数を1から10個のうちいずれかの個数を表示する。というプログラムを作成したく、次のようなプログラムを作成したのですが、表示結果に0(何も表示されない)が出てしまい意味がわからなくて困っています。1以上としたのになぜ何も表示されない結果が出るのでしょうか? import java.util.*; public class RandomTest{ public static void main(String[] args){ int rand; Random generator = new Random(); //1以上10以下のintの値をrandに rand = (int)(Math.random()*10)+1; for(int j=1; j<rand; j++){ int ran = (int)(Math.random() * 10)+1; System.out.println(ran); } } } お願いします。

    • ベストアンサー
    • Java
  • 乱数について

    Visual Studio2008を使っています。 #include<stdio.h> #include<stdlib.h> #include<time.h> int main(void){ int i; srand(time(NULL)); i=rand(); printf("%d\n",i); return 0; } 乱数を作るために上のようなプログラミングを作りました。 これを「ソリューションのビルド」すると 【warning C4244: '引数' : 'time_t' から 'unsigned int' への変換です。データが失われる可能性があります。】 と出ます。 このまま行っても乱数が出来るのですが どうしたらいいのでしょうか? 8行目を srand(time_t(NULL)); srand((unsigned)time(NULL)); と変えればいいのでしょうか? time_tでやると乱数が同じ値しか出てきません。 教えてください。

  • C言語/ランダムbeepのプログラム方法

    プログラムを書いていますが理解に苦しんでいます。 勉強し始めたばかりなのでかなりハードです。どなたか助けていただけませんか。 前に進めずにいます。 何をしたいかというと、マッチングゲームの中の一部でランダムなビープサウンドにあわせて反応して答えを返すというものです。答えられなければ点数がマイナスになります。 まず、数字をランダムに1から10の間で生成し、出た数字がある特定の数字だとビープサウンドが流れるという仕組みを考えたのですがどうでしょうか。 本当に切羽詰っています。助けてください。 // rand.cpp : Defines the entry point for the console application. // #include <stdafx.h> #include <stdlib.h> /*This header is for rand srand code)*/ int main (void) { unsigned int seed; int i,run=0; printf("Choose a level of difficulty"); scanf("%d", &seed); /*&seed is for "unsigned" int*/ printf("\n"); srand(seed); /*generate a number 0-10*/ i=1+(int) (10.0*rand()/(RAND_MAX+1.0)); /*if a number is 1, beep sound comes out*/ if(i==1) for(int j=0; j<i; j++) printf("\a"); return 0; }

専門家に質問してみよう