ユーニックス総合研究所

  • home
  • archives
  • c-ransu-hanishitei

C言語で乱数を範囲指定して取得する関数を作る

  • 作成日: 2024-03-12
  • 更新日: 2024-03-12
  • カテゴリ: C言語

C言語でたとえば0から10の範囲で乱数を得たい。
と言うような時があるとします。

そういう場合は乱数列を作るrand()を使えばいいのはわかりますが、範囲指定して乱数を得るにはどうしたらいいのでしょうか?
この記事ではその方法について解説します。

C言語や他の言語を扱うYoutubeも公開しています。
興味がある方は以下のリンクからご覧ください。

Youtubeの当チャンネル

範囲内の乱数を得る数式

指定範囲内の乱数を得る数式は以下になります。

乱数 * (最大値 - 最小値) + 最小値;  

乱数」は0~1の範囲の実数です。
最大値」は範囲指定の最大値で「最小値」は範囲指定の最小値になります。
最大値を最小値で引くと最大値から最小値までの範囲が求まります。

たとえば最大値が10で最小値が5だったとするとその範囲は5です。
これは最小値5から最大値10までの距離になります。

たとえば乱数が1だった場合は5を掛けると5になります。
これに最小値を足すと5 + 5で10になります。
つまり5から10の範囲の最大値です。

乱数が0.5だったとすると5を掛けた場合は2.5です。
これに最小値を足すと5 + 2.5で7.5になります。

乱数が0だったとすると5を掛けた場合は0です。
これに最小値を足すと5 + 0で5になり、つまり範囲指定の最小値になります。

範囲指定できる乱数生成関数を作る

先ほどの数式があれば乱数生成器を作るのは簡単です。

int rand_range(int min, int max) {  
    return ((double) rand() / RAND_MAX) * (max - min) + min;  
}  

rand()は整数の乱数を返します。実数ではないです。
そのため乱数の最大値であるRAND_MAXで値を割ります。
こうすると乱数が0~1の範囲の実数になります。

rand()doubleでキャストしているところに注意してください。
これはrand()の返す値は整数ですが、割り算では実数が必要なためです。

あとは数式通りに実装します。
引数のminが最小値、maxが最大値です。

文字列からランダムに文字を得る

rand_range()の使用例としては文字列からランダムに文字を得る処理があげられます。

#include <stdio.h>  
#include <stdlib.h>  
#include <time.h>  
#include <string.h>  

int rand_range(int min, int max) {  
    return ((double) rand() / RAND_MAX) * (max - min) + min;  
}  

int main(void) {  
    srand(time(NULL));  // 乱数のシードを初期化  

    const char *s = "Hello, World!";  
    int i = rand_range(0, strlen(s)-1);  
    printf("%c\n", s[i]);  

    return 0;  
}  

上記のsが文字列の変数です。
この文字列をstrlen()関数に渡し、文字列の長さを得ます。
そしてそれに-1して、rand_range()で得る値が文字列の長さをオーバーしないようにします。

関連記事
C言語で文字列の長さを取得する: strlen, wcslen

    int i = rand_range(0, strlen(s)-1);  

あとは乱数のiで文字列sをインデックスで参照し、出力します。
これで文字列の長さの範囲の乱数な文字を得ることができます。

配列からランダムに要素を得る

配列からランダムに要素を得る場合も文字列と近しい処理をします。

#include <stdio.h>  
#include <stdlib.h>  
#include <time.h>  
#include <string.h>  

int rand_range(int min, int max) {  
    return ((double) rand() / RAND_MAX) * (max - min) + min;  
}  

#define numof(ary) (sizeof ary / sizeof ary[0])  

int main(void) {  
    srand(time(NULL));  // 乱数のシードを初期化  

    int ary[] = {1, 2, 3, 4};  
    int i = rand_range(0, numof(ary)-1);  

    printf("%d\n", ary[i]);  

    return 0;  
}  

C言語の配列は要素数の情報を持っていません。
ですので計算式で要素数を計算します。

#define numof(ary) (sizeof ary / sizeof ary[0])  

numof()マクロは引数の配列の要素数を計算するマクロです。
sizeof aryで配列全体のバイト数が求まり、sizeof ary[0]で配列1つのバイト数が求まります。
配列全体のバイト数に要素1つのバイト数を割ると、要素数になります。

あとはこのマクロを使って文字列の時のようにrand_range()に最大値を指定するだけです。

    int i = rand_range(0, numof(ary)-1);  

注意点としてはnumof()マクロは配列には機能しますが、ポインタには機能しません。
C言語の関数の引数の配列は実質ポインタなので注意してください。

関連記事
C言語の配列の使い方

おわりに

今回はC言語の乱数の範囲指定について解説しました。
何か参考になれば幸いです。