1

I was trying to write some code in C to simulate temperature fluctuations +/- 4 from the previous value, however I'm getting some wild jumps in either direction.

The program is multi-threaded, however, even testing in isolation produces the same wrong results.

I've tried several variations on the code, thinking that it had to do with how the code was evaluating, but my errors but they all end up the same. My code is as follows:

int main(){
    srand(1); //Just for testing and predictability of outcome
    //short int temp = 20 + rand() / (RAND_MAX / 30 - 20 + 1) + 1; Initially I was initialising it at a random value between 20-30, but chose 20 for testing purposes
    short int temp = 20;
    short int new_temp, last_temp, new_min, new_max;
    last_temp = temp;
    for(int i = 0; i < 20; i++){
        //last_temp = temp; At first I believed it was because last_temp wasn't being reassigned, however, this doesn't impact the end result
        new_min = last_temp - 4;
        new_max = last_temp + 4;
        //new_temp = (last_temp-4) + rand() / (RAND_MAX / (last_temp + 4) - (last_temp - 4) + 1) + 1; I Also thought this broke because they last_temp was being changed with the prior math in the equations. Still no impact
        new_temp = new_min + rand() / (RAND_MAX / new_max - new_min + 1) + 1;

        printf("Temperature is %d\n", new_temp);
    }
    
    return 0;
}

Produces results like this.

Temperature is 37
Temperature is 26
Temperature is 35
Temperature is 36
Temperature is 38

As you can see, the first temperature reading should be within the range of 16-24, however it increases by 17 to 37, and I can't figure out why. Any insight would be appreciated. In the alternative, can anyone provide me with a clean way to simulate a random +/- without having to use a lot of embedded if statements?

M.M
  • 138,810
  • 21
  • 208
  • 365
BrownBear
  • 13
  • 3
  • 2
    Is something missing here: `RAND_MAX / + new_max` between `/` and `+`? – sj95126 Nov 02 '21 at 23:44
  • 5
    Simpler approach would be to generate a random increment between -4 to 4. – kaylum Nov 02 '21 at 23:47
  • 3
    The first thing you need to do to start debugging this issue is to break down your complex calculation. Add a couple of intermediate variables to hold the results of both sides of the calculation, so that you can step through in the debugger and see the calculation as it's being done. If you don't know how to use the debugger, now is an excellent time to learn. It's the best tool a coder has in their toolbox for finding logic errors or tracing the flow of execution. – Ken White Nov 03 '21 at 00:00
  • `the first temperature reading should be within the range of 16-24`, why? What makes you think that's the expected result from your calculation? – Martin Nov 03 '21 at 00:18
  • @Martin To get a random value within a range I used M + rand() / (RAND_MAX / (N - M + 1) + 1), taken from [link] (https://stackoverflow.com/questions/1202687/how-do-i-get-a-specific-range-of-numbers-from-rand). Subbing in the values would make this code `16 + rand() / (RAND_MAX / 24 - 16 + 1) + 1;` would it not? After your comment though, I've noticed I was missing the brackets around `new_max - new_min` which changed the output enough for me to see my error. Thank you – BrownBear Nov 03 '21 at 00:38
  • 2
    This site uses a Question/Answer format -- please do not edit the Question to contain Answers. If you would like to post a fixed version then post it as an Answer. (And explain what was fixed). – M.M Nov 03 '21 at 04:01

1 Answers1

3

There are 2 issues in this code:

  1. rand() usage
  2. last_temp value is not updating in each iteration

rand usage

rand() returns a value between 0 and RAND_MAX. You want to limit this value in [0,8] and add it to new_min, so that new_temp is limited in [last_temp-4,last_temp+4], ie [new_min,new_min+8].

To do that, you use % operator. By doing rand() % 9, you limit your random value between 0 and 8. So, the new_temp value should be: new_temp = new_min + rand() % 9.

last_temp update

You need to update the last_temp value after you assign your new_temp value like this:

new_temp = new_min + rand() % 9;
last_temp = new_temp;

So, you for loop should look like this in the end:

for(int i = 0; i < 20; i++){
    new_min = last_temp - 4;
    new_max = last_temp + 4;
    new_temp = new_min + rand() % 9;
    last_temp = new_temp;

    printf("Temperature is %d\n", new_temp);
}

And the code can be minimized to this:

int main() {
    srand(1); //Just for testing and predictability of outcome
    short int temp = 20; //or 20 + rand()%11 for values in [20,30] range
    for(int i = 0; i < 20; i++) {
        temp += -4 + rand() % 9;
        printf("Temperature is %hd\n", temp);
    }
    return 0;
}

with an outcome of:

Temperature is 23
Temperature is 25
Temperature is 22
Temperature is 21
Temperature is 18
Temperature is 21
Temperature is 19
Temperature is 19
Temperature is 16
Temperature is 17
Temperature is 15
Temperature is 14
Temperature is 12
Temperature is 11
Temperature is 10
Temperature is 12
Temperature is 12
Temperature is 10
Temperature is 10
Temperature is 6
stevp
  • 76
  • 4
  • I didn't see your comment before I updated my post. This seems to be a far better way to to achieve the result I'm looking for. Thank you – BrownBear Nov 03 '21 at 00:50
  • 1
    Using `rand() % 8` will yield 8 values between 0 and 7, you would want to use `rand() % 9`. Except actually you wouldn't, because using modulo arithmetic is subject to [modulo bias](https://stackoverflow.com/questions/10984974/why-do-people-say-there-is-modulo-bias-when-using-a-random-number-generator). It's probably not enough to matter in this case, but if you want a truly uniform distribution it takes some work. – pjs Nov 03 '21 at 02:41
  • 1
    Thank you for your comments! I changed the answer to use `rand() % 9`. Regarding modulo bias, the greater RAND_MAX is, the lesser the bias. – stevp Nov 03 '21 at 03:20