LinuxQuestions.org
Help answer threads with 0 replies.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 03-07-2005, 09:46 AM   #1
nazdrowie
Member
 
Registered: Oct 2004
Distribution: Debian
Posts: 39

Rep: Reputation: 15
srand(), rand(), RAND_MAX, or XXX weirdness


I'm having some problems running the following bitsortgen.c code on my linux machine (you can get it at http://www.cs.bell-labs.com/cm/cs/pearls/code.html -- it's from the book "Programming Pearls" by the way, which is awesome):

Code:
/* Copyright (C) 1999 Lucent Technologies */
/* From 'Programming Pearls' by Jon Bentley */

/* bitsortgen.c -- gen $1 distinct integers from U[0,$2) */

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAXN 2000000
int x[MAXN];

int randint(int a, int b)
{   return a + (RAND_MAX * rand() + rand()) % (b + 1 - a);
}

int main(int argc, char *argv[])
{   int i, k, n, t, p;
    srand((unsigned) time(NULL));
    k = atoi(argv[1]);
    n = atoi(argv[2]);
    for (i = 0; i < n; i++)
        x[i] = i;
    for (i = 0; i < k; i++) {
        p = randint(i, n-1);
        t = x[p]; x[p] = x[i]; x[i] = t;
        printf("%d\n", x[i]);
    }
    return 0;
}
I get 'Segmentation fault' errors quite often when running the program. I used gdb and ran it a couple times with a break point set at the point where p gets assigned in the second for loop of the main function, and sometimes the p value ends up being negative, hence the seg faults, I guess.

But the odd thing about it is that the program runs just fine on a SunOS -- no problems whatsoever. I've checked it out a bit, and the only difference between the two (Linux and SunOS) that I'm currently aware of is that on my Linux machine RAND_MAX = 2147483647, while on a SunOS machine RAND_MAX = 32767. However, I don't see how that could possibly be causing the problem and resulting in negative p values on a Linux machine.

You can compile the program and see for yourself (run it a couple times and for a couple sets of values). When you run it, just make sure that you pass it two numbers as command-line arguments, with the first one smaller than the second, and the second no larger than 2 million.

Any clues?
 
Old 03-07-2005, 11:28 AM   #2
Hko
Senior Member
 
Registered: Aug 2002
Location: Groningen, The Netherlands
Distribution: Debian
Posts: 2,536

Rep: Reputation: 111Reputation: 111
Quote:
I'm currently aware of is that on my Linux machine RAND_MAX = 2147483647, while on a SunOS machine RAND_MAX = 32767. However, I don't see how that could possibly be causing the problem and resulting in negative p values on a Linux machine.
That's exactly where the problem is. On linux RAND_MAX = 2147483647, which happens to be also the maximum integer value (at least on 32-bits Linux). When you overflow an int variable, it wraps around to negative values. To see this happening, try this:
Code:
int main(int argc, char *argv[])
{
    int p;
    p = 2147483647;  /* max int */
    printf("p = %d\n", p);
    p = p +1;  /* Add 1 */
    printf("p+1 = %d\n", p);
    return 0;
}
So when the randint() function does: RAND_MAX * rand() + rand() it will surely overflow the maximum int value (serveral times at once probably). So you will get about 50% negative values...

You cannot change the maximum value rand() will return (AFAIK). So to fix this change the function to:
Code:
int randint(int a, int b)
{
    return a + (65535 * rand()%65535 + rand()%65535) % (b + 1 - a);
}
or, simpler:
Code:
int randint(int a, int b)
{
    return a + rand() % (b + 1 -a);
}
 
Old 03-07-2005, 12:45 PM   #3
nazdrowie
Member
 
Registered: Oct 2004
Distribution: Debian
Posts: 39

Original Poster
Rep: Reputation: 15
Thank you for the excellent reply!

I suppose I just assumed that: first, the (RAND_MAX * rand() + rand()) computation would be safely handled -- no overflow -- so long as it wasn't cast to an integer first and then used in the computation, and second, that the modulo operator would take care of the rest. It turns out my first assumption was off! Silly rabbit, such tricks aren't for c
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
"Error, some other host already uses address XXX.XXX.XXX.XXX" mwbb_support Linux - Networking 5 01-20-2014 08:59 AM
Problem getting connection with a DLink Router with IP 10.xxx.xxx.xxx kezira Fedora 9 11-28-2005 10:31 PM
Problem getting connection with a DLink Router after setting static IP 10.xxx.xxx.xxx kezira Linux - Networking 1 11-09-2005 10:27 PM
Host XXX.XXX.XXX.XXX is not allowed to connect to this MySQL server ocavid Linux - Newbie 2 03-16-2005 09:40 AM
# ping -b xxx.xxx.xxx.255 porous Linux - Networking 2 10-13-2003 12:34 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 02:37 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration