-3

Well I feel my question is bit more complex compared to other questions. I realized this while trying to solve it.

I tried using

int number = rand() % (INT_MAX - INT_MIN + 1) + INT_MIN;
rand() % (INT_MAX + INT_MIN + 1) + rand() % INT_MIN;

However, I got floating point exception 8 error. No warnings, that's really strange!

Also, from time.h, I used srand((unsigned)time(NULL)) for new random number every time I execute my code.

But whatever I try either I get incorrect results or floating point exception.

I am really curious as to overflow & underflow, how it's happening and can such a random number be actually generated?

I basically want to generate a number in C greater than INT_MIN and lesser than INT_MAX.

I tried lots of logic but I got incorrect result.

Andrew T.
  • 4,701
  • 8
  • 43
  • 62
  • Please let me know what is wrong with my post. I have just begun to learn C programming. – user2285161 Sep 25 '15 at 02:30
  • possible duplicate of [How to generate a random number from within a range](http://stackoverflow.com/questions/2509679/how-to-generate-a-random-number-from-within-a-range) – John3136 Sep 25 '15 at 02:31
  • 1
    Two issues with your post: 1. The answer is easy to find with a simple Google search. 2. SHOUTING IN THE TITLE. – John3136 Sep 25 '15 at 02:32
  • I tried that solution before posting my question. – user2285161 Sep 25 '15 at 02:33
  • I am really sorry. I googled but always I am going wrong. Maybe I am novice to C right now. – user2285161 Sep 25 '15 at 02:33
  • 1
    I have a feeling that `(INT_MAX - INT_MIN + 1)` is equal to 0. BTW, I DIDN'T DOWN VOTE, BUT THE CAPS, and the yellow text are probably annoying to some people. – user3386109 Sep 25 '15 at 02:33
  • Novice or not, you've got to learn to use a debugger. In your case I'd break the computation into pieces and see what those pieces produce. For instance I feel the `(INT_MAX - INT_MIN + 1)` is going to overflow right there. – YePhIcK Sep 25 '15 at 02:34
  • Honestly, I tried past 2 days using netbeans on mac , code signing didn't work. Installed gdb & Xcode but Xcode removed C debugging features too.The moment I click debugger in netbeans , it freezes.I am on Yosemite on Retina macbook pro 13" (haskell version). I strangely enough cannot change color to anything else , tried editing it stays yellow :( – user2285161 Sep 25 '15 at 02:36
  • @John3136 A careful read of the suggested duplicate indicates a question and answers that focuses on a significant sub-range of `int` and not its entire range. Even the top rated answer requires `0 <= max <= RAND_MAX` which does not meet this post's `[INT_MIN...INT_MAX]` requirement. – chux - Reinstate Monica Sep 25 '15 at 04:50

2 Answers2

2

(INT_MAX - INT_MIN + 1) is probably going to overflow (since they're int literals) and produce 0, explaining your error (you're dividing by 0).

Changing to ((long)INT_MAX - INT_MIN + 1) would avoid the overflow (assuming long is bigger than int, which is not the case for Visual Studio on Windows, where you'd need to cast to long long).

That said, you're not going to get the results you want with a single rand call; it only produces numbers between 0 and RAND_MAX; RAND_MAX is usually 32767, so you'd end up covering only a trivial portion of the possible range for int on most systems (where int is usually 32 bits).

To make this work, you'd need to generate enough bits to fill an int. Something like:

#include <stdlib.h>
#include <limits.h>
#include <math.h>

/* Assumes srand() has been called with an appropriate seed at some point
   Code assumes C99 is available; minor tweaks needed for older compilers.
 */
int gen_random_int() {
    const int BITS_PER_RAND = (int)(log2(RAND_MAX/2 + 1) + 1.0); /* Or log(RAND_MAX + 1) / log(2) with older language standards */
    int ret = 0;
    for (int i = 0; i < sizeof(int) * CHAR_BIT; i += BITS_PER_RAND) {
        ret <<= BITS_PER_RAND;
        ret |= rand();
    }
    return ret;
}

You don't even need to bother with INT_MIN and INT_MAX, because this fills in an int directly; the excess bits of random generated overflow and get discarded.

ShadowRanger
  • 143,180
  • 12
  • 188
  • 271
  • `INT_MAX - INT_MIN + 1ULL` would be cleaner as no cast is needed – phuclv Sep 25 '15 at 03:04
  • OOC, does the standard actually guarantee it would be evaluated in that order? If `INT_MAX - INT_MIN` is evaluated first, you've already overflowed. I know expanding the left side value involved in the overflowing calculation will work, but I'm not confident that expanding the `1` wouldn't invoke implementation specific behavior. – ShadowRanger Sep 25 '15 at 03:07
  • In the same expression, the common type will be used no matter what order they're evaluated in – phuclv Sep 25 '15 at 03:09
  • Well I think it causes overflow since I get floating point error .In fact in any order I do INT_MAX - INT_MIN , I am guaranteed that error . Tried that function, compiler throws "error: initializer element is not a compile-time constant static const int BITS_PER_RAND = (int)log2(RAND_MAX + 1); /* Or log(RAND_MAX + 1) / log(2) with older language standards */" – user2285161 Sep 25 '15 at 03:11
  • @user2285161: Without an upcast of some sort (implicit as Lưu describes or explicit as my answer mentions), you'd overflow. The overflow doesn't directly cause the exception though; the exception is because the resulting 0 is used for division, and dividing (remainder operations are equivalent to division for this purpose) by zero causes the exception you're seeing. Reasonable compilers should notice a division by a compile time constant of 0 though, so that's a little strange. – ShadowRanger Sep 25 '15 at 03:16
  • @user2285161 remove `static` from the declaration, or calculate the number of bits yourself. `INT_MAX - INT_MIN` **always** overflow because it results in **4294967295** (2^32-1), assuming 32-bit int, and that is outside of int's range. Moreover, `INT_MAX - INT_MIN + 1` results in 0 (as the low 32 bits of 4294967296 is all 0) which causes the exception – phuclv Sep 25 '15 at 03:29
  • Ah, sorry. My mistake on the constant. I'll fix. – ShadowRanger Sep 25 '15 at 03:31
  • It's working superb... However , just for fun , if I want to generate a number such that INT_MAX < number < INT_MIN means number can be negative also , right ? Or am I thinking way too much :) – user2285161 Sep 25 '15 at 04:17
  • This is filling in a signed integer and left-shifting into the sign bit, so it will generate both positive and negative numbers in the complete range from `INT_MIN` to `INT_MAX`, inclusive on both ends (`INT_MAX` < `number` < `INT_MIN` makes no sense, because that's asking the `number` to be greater than a huge positive number and less than a huge negative number). I can't be 100% sure it will work as expected on truly bizarre architectures, but on your standard two's complement (or one's complement for that matter) architecture, the unsigned values still produce signed outputs. – ShadowRanger Sep 25 '15 at 04:22
  • `RAND_MAX + 1` in `log2(RAND_MAX + 1)` may `int` overflow --> UB. Alternative: `(log2(RAND_MAX/2 + 1) + 1.0)`. – chux - Reinstate Monica Feb 13 '18 at 22:25
  • `ret <<= BITS_PER_RAND;` is also subject to `int` overflow (UB). – chux - Reinstate Monica Feb 13 '18 at 22:28
  • @chux: True on both counts. I incorporated your suggested fix for `RAND_MAX + 1` overflowing, if you have suggestions for fully defined ways to populate the `int` I'm open to them (in practice I've never seen overflow misbehave in this case, but my experience is obviously not exhaustive, nor normative). – ShadowRanger Feb 13 '18 at 23:52
1

INT_MAX - INT_MIN + 1 is int overflow and therefore undefined behavior.

The behavior your system experienced was a divide by 0 as that is often, though not specified, result of INT_MAX - INT_MIN + 1 --> 0.

rand() generates an int in the range [0...RAND_MAX]. Since RAND_MAX <= INT_MAX, it could take multiple calls to construct an int in the range [0...INT_MAX] let alone in your quest of [INT_MIN...INT_MAX].

Below is a generic approach. It is not highly efficient but simple and obviously amendable for all sorts of types.

int rand_int(void) {
  union {
    int i;
    unsigned char uc[sizeof (int)];
  } u;
  for (size_t i = 0; i < sizeof u.uc; i++) {
    u.uc[i] = rand();
  }
  return u.i;
}

It technically can cause UB on rare machines that have a trap value for int.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • I created a custom formula and finally I am able to generate a number both positive and negative between INT_MAX & INT_MIN. :) Thanks for the suggestions. They are really so precious for me ! :) – user2285161 Sep 25 '15 at 05:23
  • Random functions have many pitfalls. Suggest posting your solution here as an answer or for review at `http://codereview.stackexchange.com` – chux - Reinstate Monica Sep 25 '15 at 10:30