-1

How do I go about generating random integer values between a range (in this case 1-12 including 1 and 12) in the C language?

I've read about seeding (srand()) and using rand() within a range but am unsure about how to go about it.

Edit: Here is what I have so far

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

// Craps Program
// Written by Kane Charles
// Lab 2 - Task 2

// 7 or 11 indicates instant win
// 2, 3 or 12 indicates instant los
// 4, 5, 6, 8, 9, 10 on first roll becomes "the point"
// keep rolling dice until either 7 or "the point is rolled"
//      if "the point" is rolled the player wins
//      if 7 is rolled then the player loses

int wins = 0, losses = 0;
int r, i;
int N = 1, M = 12;
int randomgenerator();


main(void){

  /* initialize random seed: */
  srand (time(NULL));
  /* generate random number 10,000 times: */
  for(i=0; i < 10000 ; i++){
     int r = randomgenerator();
     if (r = 7 || 11) {
        wins++;
     }
     else if (r = 2 || 3 || 12) {
        losses++;
     }
     else if (r = 4 || 5 || 6 || 8 || 9 || 10) {
        int point = r;
        int temproll;
        do
        {
            int temproll = randomgenerator();

        }while (temproll != 7 || point);

        if (temproll = 7) {
            losses++;
        }
        else if (temproll = point) {
            wins++;
        }
     }
  }
    printf("Wins\n");
    printf("%lf",&wins);
    printf("\nLosses\n");
    printf("%lf",&losses);
}

int randomgenerator(){
    r = M + rand() / (RAND_MAX / (N - M + 1) + 1);
    return r;
}
hjpotter92
  • 78,589
  • 36
  • 144
  • 183
Kane Charles
  • 379
  • 3
  • 10
  • 19
  • See here as well: http://stackoverflow.com/questions/5008804/generating-random-integer-from-a-range (C++, but answers cover C as well.) – jogojapan Apr 12 '13 at 02:32
  • 1
    [This site](http://www.azillionmonkeys.com/qed/random.html) might be of interest, to you... – autistic Apr 12 '13 at 02:36
  • You've accepted Chahaun's answer as correct, but note my concern about roundoff error. His algorithm probably does not in fact uniformly sample from the range, i.e., doesn't behave correctly. – Matt Phillips Apr 12 '13 at 02:59
  • @MattPhillips I haven't really thought about it in depth yet, but what you say sounds like a useful consideration. Perhaps you should add some explanation of this to your answer? – jogojapan Apr 12 '13 at 03:10
  • 1
    @jogojapan Ok I added some comments. – Matt Phillips Apr 12 '13 at 03:27
  • There's no way this program is doing what you think it is. – cat May 10 '16 at 01:40

2 Answers2

0

The simple way is

#include <stdlib.h>
#include <sys/time.h>

int main(void)
{
    struct timeval t1;
    gettimeofday(&t1, NULL);
    srand(t1.tv_usec * t1.tv_sec);

    int a = 1, b = 12;

    int val = a + (b-a) * (double)rand() / (double)RAND_MAX + 0.5;

    return 0;
}

Edit, since someone asked: You really do have to use floating point arithmetic to get this to come out right (or as right as it can given rand()'s limitations such as they are). Any solution which relies purely on integer arithmetic and rand() will of necessity use \ or %, and when this happens you will get roundoff error--where c and d are declared int and c = 5 and d = 2, for example, c/d == 2 and d/c == 0. When comes to sampling from a range, what happens is that in compressing the range [0, RAND_MAX] to [a, b], you have to do some kind of division operation since the former is so much larger than the latter. Then roundoff creates bias (unless you get really lucky and things evenly divide). Not a truly thorough explanation but I hope that conveys the idea.

Matt Phillips
  • 9,465
  • 8
  • 44
  • 75
  • 1
    Can you please how this works and why it is dirty? – Kane Charles Apr 12 '13 at 02:31
  • @KaneCharles `rand()` generates a number from 0 to `RAND_MAX`. Dividing by `RAND_MAX` then gives you a random value on [0, 1] which can then be scaled according to the range of discrete values you want. As for being dirty, actually I think I was thinking of another way this gets done sometimes with `%`--this answer is not dirty! Edited accordingly. :) – Matt Phillips Apr 12 '13 at 02:35
  • 1
    It's dirty because it uses C++ in a C question, and because it uses rand, which just isn't all that great. – autistic Apr 12 '13 at 02:39
  • @modifiablelvalue Sorry where's the C++? – Matt Phillips Apr 12 '13 at 02:42
  • @KaneCharles Note my edit, I've generalized the answer to make the parameterization by range obvious. – Matt Phillips Apr 12 '13 at 02:43
  • 1
    @MattPhillips: `#include ` doesn't work in a C compiler. It's a C++ header. – dreamlax Apr 12 '13 at 02:44
  • Thanks for taking into account my request. +1 for raising valid points. There are a few things I had to do to get this to compile, though, notably: use `struct timeval` instead of just `timeval`, and of course add `int main() { .... return 0; }`. – jogojapan Apr 12 '13 at 03:50
  • @jogojapan Thanks, happy to help. I've incorporated your notes into the answer. – Matt Phillips Apr 12 '13 at 03:52
-1

You should use: M + rand() / (RAND_MAX / (N - M + 1) + 1)

Don't use rand() % N (which tries to return numbers from 0 to N-1). It is poor, because the low-order bits of many random number generators are distressingly non-random. (See question 13.18.)

Example code:

#include <stdio.h>      /* printf, scanf, puts, NULL */
#include <stdlib.h>     /* srand, rand */
#include <time.h>       /* time */
int main ()
{
  int r, i;
  int M = 1,
      N = 12;
  /* initialize random seed: */
  srand (time(NULL));

  /* generate number between 1 and 12: */
  for(i=0; i < 10 ; i++){ 
     r = M + rand() / (RAND_MAX / (N - M + 1) + 1);
     printf("\n%d", r);
  }
  printf("\n") ;
  return EXIT_SUCCESS;
}

It's working here at codepad.

Nisse Engström
  • 4,738
  • 23
  • 27
  • 42
Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
  • 1
    [This site](http://www.azillionmonkeys.com/qed/random.html) might also be of interest to you, my friend... – autistic Apr 12 '13 at 02:41
  • @modifiablelvalue Thanks interesting :) Its good site. Have you gone to the site I linked in this answer. – Grijesh Chauhan Apr 12 '13 at 02:45
  • Where the range is large, roundoff error will bias the distribution towards lower values. – Matt Phillips Apr 12 '13 at 02:49
  • @modifiablelvalue hi do you have idea on page-faults and virtual memories? – Grijesh Chauhan Apr 12 '13 at 02:55
  • I need to produce 10,000 random numbers that can only be between 1 and 12, will this be able to do so? EDIT: Works perfectly, thanks. – Kane Charles Apr 12 '13 at 02:57
  • 1
    @KaneCharles Not if you care about loaded dice... – autistic Apr 12 '13 at 02:59
  • 1
    The answer is INCORRECT as N and M are mistaken. Please take Matt's concern seriously. – Yang Apr 12 '13 at 03:07
  • In regards to your line: `srand (time(NULL));` I'm getting the error: `/home/kane/C Programming/src/Craps.cpp|24|error: ‘time’ was not declared in this scope` – Kane Charles Apr 12 '13 at 03:22
  • @Yang Not if you care about loaded dice... KaneCharles: `#include `, as [the manual for `time`](http://pubs.opengroup.org/onlinepubs/009695399/functions/time.html) indicates. Having said that, I wouldn't expect a person who asks a question like this to be able to read the manual. *sigh* – autistic Apr 12 '13 at 03:27
  • I'm new to this so I'm still learning the basics. I've edited my original post with the code I am using, it is still throwing a few errors but I hope to fix them myself. – Kane Charles Apr 12 '13 at 03:31
  • @GrijeshChauhan Would you like to ask a more specific question [in chat](http://chat.stackoverflow.com/rooms/28070/room-for-modifiable-lvalue-and-grijesh-chauhan)? – autistic Apr 12 '13 at 03:35
  • @KaneCharles Which book are you reading? – autistic Apr 12 '13 at 03:36
  • I'm doing this from a course at uni, this is only the second week's lab so I'm just working off what the lectures have shown us. I've done Java before so some of this is familiar territory. @modifiablelvalue – Kane Charles Apr 12 '13 at 03:39
  • @modifiablelvalue Actually, probability adjustment for uniform distribution has been concluded in the given `M + rand() / (RAND_MAX / (N - M + 1) + 1)`. It's just that N and M are mistaken. I was just kindly recalling the comprehension behind. – Yang Apr 12 '13 at 03:39
  • @KaneCharles Disregard the similarity you believe C has to Java. In C, there is a concept known as "undefined behaviour" (research it yourself; you're a Uni student...). Code that invokes UB might appear to work on your system, but only by coincidence. It might then fail subtly or in devastating ways on other systems. Hence, you can't learn C by mashing your face on the keyboard and fixing the resulting errors like you can in Java. As a Uni student, it's important that you research (eg. reading books and manuals) independently, in your own time. I'm sure your lecturer would agree. – autistic Apr 12 '13 at 03:43
  • @Yang rand isn't required to produce uniformly distributed values. A perfectly compliant implementation of rand might produce 0 every time. – autistic Apr 12 '13 at 03:47
  • @Yang OP updated his question since I posted my answer. rand() don't produce uniformly distributed values. – Grijesh Chauhan Apr 12 '13 at 04:26
  • @KaneCharles Trust on what you understands I posted a link at first line in my answer. read from related pages also. – Grijesh Chauhan Apr 12 '13 at 04:28