プロが教えるわが家の防犯対策術!

C 初心者です。
表題のように、unsigned longのスケールの乱数をつくりたいんですが、以下のように記述すると値がいつも同じになります。この理由と、正しく動作するにはどう直したらいいのか教えてください。

unsigned long ul;

ul = 4294967295UL * rand() / (RAND_MAX + 1);

値は常に131071でした。

A 回答 (5件)

 No.2の方が書かれているとおり、最初の積算で unsigned intの扱える値の範囲を超えて(オーバーフロー)しまっているものと思われます。



 除算を先にすれば一応解決するはずです。

ul = (unsigned long)(4294967295.l * (rand() / (double)(RAND_MAX + 1)));


 ただ、環境にも依りますが rand()の精度が問題になりそうです。
 RAND_MAXが 4294967295ならば問題はありませんが、それよりも小さな値の場合、0~4294967295の値の中の分解能が低くなるので、同じ値が出る確率が 1/4294967295よりも大きくなります。
(うちの VC7.1は RAND_MAXが 32767だったので、同じ値が出る可能性は 1/32767です)
 その確率を 1/4294967295にしたい場合は、例えば下記のように少し工夫が必要です。

 int d = ULONG_MAX / RAND_MAX;
 int m = ULONG_MAX % RAND_MAX + 1;
 unsigned long ul = rand() * d + rand() % m;

この回答への補足

指摘の通り直したところ、精度があがったようです。
と言うのは、
ul = 4294967295UL * (rand() / (RAND_MAX + 1.0));
で出てくるulは、16進に直すと必ず e98dffff,3341ffff などfが4つ続く数字となりました。d,mを導入することで、それが解消されたようです。

補足日時:2006/04/25 11:41
    • good
    • 0

スケーリングして拡大しても、隙間が空いてしまうので、2階建てにしたほうがよいと思います。


-- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< -- 8< --
#include <stdio.h>
#include <time.h>
#include <stdlib.h>

int
main(void)
{
unsigned long long rnd;
int cnt[100];
int i;

srand(time(0));

for (i = 0; i < 100; i++) {
cnt[i] = 0;
}
for (i = 0; i < 100000; i++) {
rnd = (unsigned long long) rand() *RAND_MAX + rand();
cnt[(int)((double) rnd / RAND_MAX / RAND_MAX * 100)]++;
}
for (i = 0; i < 100; i++) {
printf("%5d%10d\n",i, cnt[i]);
}

return 0;
}

この回答への補足

ちょっと私には難しいですが、徐々に理解していこうと思います。
回答ありがとうございます。

補足日時:2006/04/25 11:51
    • good
    • 0

C初心者なのになぜそんなことがしたいのかが疑問。

この回答への補足

仕事上必要になったもので・・・。
今まではVBを使っていましたが、今回Cで書かざるを得なくなりました。

補足日時:2006/04/25 11:48
    • good
    • 0

思ったことその1: かけ算のところでオーバーフローする可能性があります.


その2: そんな広い範囲にするために rand を使うのは無謀です. 別の関数を探すべし.

この回答への補足

回答ありがとうございます。
ご指摘の通り、オーバーフローを起こしているようです。

ul = 4294967295UL * rand() / (RAND_MAX + 1);


ul = 4294967295UL * (rand() / (RAND_MAX + 1.0));
に直したところ、うまくいきました。
1の部分も1.0でないとまずいようです。

補足日時:2006/04/24 21:56
    • good
    • 0

srand()とtima.hを使うんじゃないか?

この回答への補足

回答ありがとうございます。
srand(time(NULL));
を追加して実行しても値が変わりませんでした。

補足日時:2006/04/24 20:46
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!