Thread: Why does this UL int appear to exceed its limit?

  1. #1
    Registered User
    Join Date
    Feb 2010
    Posts
    31

    Why does this UL int appear to exceed its limit?

    In the following code I'm not sure how the rand function operates successfully, given that the unsigned long int variable 'next' appears to exceed that variable type's limit of 4294967295 (Thanks for any help):

    Code:
    #include <stdio.h>
    
    	unsigned long int next = 1;
    
    int main()
    {
    
    	int rand(void);
            void srand(unsigned int);
    
    	int i;
    
    	i = 5;
    
    	srand(i);
    
    	i = rand();
    
    	printf("\nOutput: %d\n\n", i);
    
    return 0;}
    
    
    /*rand: return pseudo-random integer on 0..32767 */
    
    int rand(void){
    
    	next = next * 1103515245 + 12345;
    
    return (unsigned int)(next/65536) % 32768;}
    
    
    /*srand: set seed for rand()*/
    
    void srand(unsigned int seed){
    
    	next = seed;
    }

  2. #2
    Registered User matrixx333's Avatar
    Join Date
    Mar 2009
    Posts
    67
    Someone please correct me if I'm wrong, but I see a couple of problems here.

    First, rand() and srand() are functions defined in stdlib.h. Are you trying to implement your own versions of these functions? Second problem I see is you are declaring your function prototypes inside of main():

    Code:
    #include <stdio.h>
    
    int main()
    {
           int rand(void);
           void srand(unsigned int);
           ...........
    }

    They should be defined outside of the main() loop like:

    Code:
    #include <stdio.h>
    
    int rand(void);
    void srand(unsigned int);
    
    int main(void) {
           .......
    	
    }
    Also you should use "void" as the argument to main() if you aren't going to pass any command line arguments, as in the example I provided earlier. Now, onto your original question. The value of next is being assigned the difference of the result of the expression:

    Code:
    next = next * 1103515245 + 12345; //which is 5517588570
    and the size of the data type (unsigned long int):

    Code:
    5517588570 - 4294967296 = 1222621274
    The reason next is being assigned 1222621274 is because of two's complement, if I'm not mistaken.

    1222621274 is is then divided by 65536, which gives the answer of 18655. Since you are typecasting the return value as an int, and the result of the modulus division is less than 1, it ignores everything after the whole number 18655.

    Hope this helps
    Last edited by matrixx333; 08-25-2010 at 06:59 AM.

  3. #3
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by matrixx333 View Post
    Someone please correct me if I'm wrong, but I see a couple of problems here.

    First, rand() and srand() are functions defined in stdlib.h. Are you trying to implement your own versions of these functions? Second problem I see is you are declaring your function prototypes inside of main():
    Neither of those is a problem. One is allowed to defined their own version of certain functions and not include the relevant header file that normally gives those function definitions. What is shown here looks like an average rand() implementation from 10-20 (or more) years ago.

    Secondly, whilst declaring function prototypes inside a function is not the normal way to do it, there isn't actually a problem with doing it that way in the example posted.
    Also you should use "void" as the argument to main() if you aren't going to pass any command line arguments, as in the example I provided earlier.
    If this is being compiled as C then yes, but people also frequently post in the wrong forum.
    The reason next is being assigned 1222621274 is because of two's complement, if I'm not mistaken.
    The actual answer to the question is that it doesn't exceed 4294967295 because the rand() function makes strategic use of arithmetic overflow. Several of the upper bits are lost on each multiply & add.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  4. #4
    Registered User
    Join Date
    Feb 2010
    Posts
    31
    Thanks for your help both.

    Quote Originally Posted by iMalc View Post
    The actual answer to the question is that it doesn't exceed 4294967295 because the rand() function makes strategic use of arithmetic overflow. Several of the upper bits are lost on each multiply & add.
    How is this code processed then, such that the function 'next' doesn't exceed its limit? How are upper bits lost and the calculation still successfully made?


  5. #5
    Just a pushpin. bernt's Avatar
    Join Date
    May 2009
    Posts
    426
    How is this code processed then, such that the function 'next' doesn't exceed its limit? How are upper bits lost and the calculation still successfully made?
    That's just how the CPU functions. It adds bits just like you and I would (except in binary), by adding corresponding digits and keeping track of the carry. When it gets to the most significant bit (so in the case of unsigned int, 2^31) there is no more room for the carry, so it is ignored.
    Consider this post signed

  6. #6
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Say you're dealing with four-bit numbers and you want to multiply six by ten.

    In binary six = 0110 and ten = 1010.
    The result would normally be sixty right? Which is 111100 in binary

    But because the variables are only four-bit, all we store is the lower 1100 and the top two ones are simply thrown away, resulting in a decimal value of just twelve.
    My homepage
    Advice: Take only as directed - If symptoms persist, please see your debugger

    Linus Torvalds: "But it clearly is the only right way. The fact that everybody else does it some other way only means that they are wrong"

  7. #7
    Registered User
    Join Date
    Feb 2010
    Posts
    31
    Thank you for your help. I got there in the end. One of the problems was that I didn't realise that the higher order bits ignored in calculating next wouldn't affect the result of the following division and modulus operation (I worked out that the division shifts the bits only 4 to the right and the modulus returns the value of the lowest 2 bytes). This led to me erroneously deducing that I was getting an answer I shouldn't have. Although, I think I was expecting some kind of warning from the compiler when an overflow happens.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 3
    Last Post: 08-16-2010, 10:00 AM
  2. memory leak
    By aruna1 in forum C++ Programming
    Replies: 3
    Last Post: 08-17-2008, 10:28 PM
  3. Working with random like dice
    By SebastionV3 in forum C++ Programming
    Replies: 10
    Last Post: 05-26-2006, 09:16 PM
  4. getting a headache
    By sreetvert83 in forum C++ Programming
    Replies: 41
    Last Post: 09-30-2005, 05:20 AM
  5. How do you search & sort an array?
    By sketchit in forum C Programming
    Replies: 30
    Last Post: 11-03-2001, 05:26 PM