Thread: portable random function: can someone explain it?

  1. #1
    Registered User fsx's Avatar
    Join Date
    Apr 2009
    Posts
    29

    portable random function: can someone explain it?

    Hello,
    I have been told that this is a portable random function (and it is, it works perfectly!) but I would like to understand its inner mechanisms.
    Since I would like to focus on clean and portable code, but still I'm following both books and the 'net without any "official" teacher (so with many teachers, which is you all that know more than me), can someone redirect me to a decent resource or explain it directly?

    I hope I am not asking too much.

    Thanks in advance =)

    Code:
         {
             time_t t = time(NULL);
    
             while (t > 0u - 1 + 0.0) {
                 t /= 2;
             }
             srand(t);
         }

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    It is ensuring that t is in the range of unsigned integers. 0u - 1 + 0.0 will give you the largest unsigned value in the form of a double.

    It is doing this to avoid UB (Undefined Behaviour) where t is too large to fit in the unsigned int type that srand accepts. t [or is even quite likely to be] may be a 64-bit integer, and C standard says that if you do x = y where y is a larger integer type than x, then it is undefined [may launch nuclear missiles, crash the program or just work].

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    The "inner workings" of rand(), srand() and time()? Since the code you posted does not make much sense (it might if there were more context), it's impossible to say if you are actually using them right...for example, when used as the seed value for srand(), it seems very strange to be performing operations on the value returned by time, unless this is some method to shake up the seed so you can call time -- srand -- rand repeatedly with no delay. But I'm not sure if that would ever be anything but overkill, anyway; one seed per program invocation should be enough. Ie, don't bother calling srand() more than once in your code.

    [edit] okay, matsp has explained this. Sorry. I just noticed that is "0u", not "Ou" (which I thought would be some variable). Never seen 0u before...
    Last edited by MK27; 05-14-2009 at 06:49 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  4. #4
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Hmm...look at that:
    Code:
    #include <stdio.h>
    
    int main() {
    	double X = 0u - 1 + 0.0;
    	printf("%lf\n",X);
    	return 0;	
    }
    Output: 4294967295.000000

    It doesn't work as an int tho (ie, I tried 0u - 1 + 0, haha). What's the deal with this "0u" formulation?
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  5. #5
    Registered User fsx's Avatar
    Join Date
    Apr 2009
    Posts
    29
    Quote Originally Posted by MK27 View Post
    Hmm...look at that:
    Code:
    #include <stdio.h>
    
    int main() {
    	double X = 0u - 1 + 0.0;
    	printf("%lf\n",X);
    	return 0;	
    }
    Output: 4294967295.000000

    It doesn't work as an int tho (ie, I tried 0u - 1 + 0, haha). What's the deal with this "0u" formulation?
    unsigned, perhaps?

  6. #6
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by fsx View Post
    unsigned, perhaps?
    signedness is not the difference between an int and a double tho.

    "0s" does not appear to be valid, so this is not some special macro.

    Also, "int x = -4u" still comes out as -4, I guess the types mismatch.
    Last edited by MK27; 05-14-2009 at 09:01 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  7. #7
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    0u means that the value is UNSIGNED, rather than signed. If you write 0 - 1 + 0.0 then you get -1.0 as the float value. There is obviously no difference in the bit-value, but converting a signed integer to double will give you a different result than converting an unsigned value.

    There are several postfix modifiers:
    L for long
    U for unsigned
    F for float
    If you do not specify it, it is up to the default of the compiler to determine what the type is (signed "normal length" integer if it fits, for example, double if it's got a decimal point).

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  8. #8
    Complete Beginner
    Join Date
    Feb 2009
    Posts
    312
    Quote Originally Posted by MK27 View Post
    Hmm...look at that:
    Code:
    #include <stdio.h>
    
    int main() {
    	double X = 0u - 1 + 0.0;
    	printf("%lf\n",X);
    	return 0;	
    }
    Output: 4294967295.000000

    It doesn't work as an int tho (ie, I tried 0u - 1 + 0, haha). What's the deal with this "0u" formulation?
    0u is an unsigned int with a value of zero. Subtracting 1 yields the largest possible value for unsigned ints (actually, it yields undefined behavior, but our current machines silently wrap around; the correct value of 0u-1 would be something like NaN). Adding 0.0 converts the unsigned int value to a floating point type. Now you can safely assign it to X.

    Suppose you omit the "u" in "0u". Then 0 is per default of type int, hence 0-1 == -1. Adding 0.0 yields -1.0.

    Greets,
    Philip

    EDIT: matsp was faster.
    All things begin as source code.
    Source code begins with an empty file.
    -- Tao Te Chip

  9. #9
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by Snafuist View Post
    Adding 0.0 converts the unsigned int value to a floating point type. Now you can safely assign it to X.
    That was a pretty complete explanation, but (out of idle curiosity), why does
    Code:
    unsigned int X = 0u -1;
    still yield "-1" (which I thought an unsigned int could not be that...). I notice
    Code:
    double X = 0u - (float)1;
    just gives -1.0, so I presume this is all a trick played on the compiler.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  10. #10
    Making mistakes
    Join Date
    Dec 2008
    Posts
    476
    normally, the first snippet should yield UINT_MAX. But if that's converted into a signed int, it will probably yield -1. In the second one, the constants are promoted, so it will calculate in floating-point.

  11. #11
    Complete Beginner
    Join Date
    Feb 2009
    Posts
    312
    Quote Originally Posted by MK27 View Post
    That was a pretty complete explanation, but (out of idle curiosity), why does
    Code:
    unsigned int X = 0u -1;
    still yield "-1" (which I thought an unsigned int could not be that...).
    I suppose you're using printf("%d", X) to print the value of X, which interprets the value of X as signed int. Note that the binary representations of (unsigned int)-1 and (signed int)-1 are the same. In fact, it doesn't matter whether you're using signed or unsigned int variables: the binary representations are the same regardless of the operations you perform on the variables. Do you know Two's Complement?

    Greets,
    Philip
    All things begin as source code.
    Source code begins with an empty file.
    -- Tao Te Chip

  12. #12
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by Snafuist View Post
    I suppose you're using printf("%d", X) to print the value of X, which interprets the value of X as signed int. Note that the binary representations of (unsigned int)-1 and (signed int)-1 are the same. In fact, it doesn't matter whether you're using signed or unsigned int variables: the binary representations are the same regardless of the operations you perform on the variables. Do you know Two's Complement?
    Yes (I understand why 0u -1 would be...), and it was using %d and not %u (silly me), by way of which plain ol' "int X = 0u - 1" does work for this. I also then thought there must be some reason for matsp to use an obfuscation of such (time_t is not a double), but actually the OP is from an anonymous source.

    Live and learn.
    Last edited by MK27; 05-14-2009 at 10:48 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  13. #13
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Incidentally, I suggest reading Prelude's article on using rand(); she provides another way of seeding with srand() using time() that is portable.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  14. #14
    Registered User
    Join Date
    Apr 2004
    Posts
    210
    So, just for the fun of it, how about this:

    Code:
      time_t t = time(NULL);
    
      while (t > (t & ~0)) {
        t /= 2;
      }
    
      srand(t);
    I say it works, who says it doesn't ?

  15. #15
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Nyda
    I say it works, who says it doesn't ?
    I'd say that it is not guaranteed to work. As far as I can tell, time_t is permitted to be of a floating point type, but bitwise and requires that both operands be of integer types.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Getting an error with OpenGL: collect2: ld returned 1 exit status
    By Lorgon Jortle in forum C++ Programming
    Replies: 6
    Last Post: 05-08-2009, 08:18 PM
  2. Replies: 28
    Last Post: 07-16-2006, 11:35 PM
  3. Calling a Thread with a Function Pointer.
    By ScrollMaster in forum Windows Programming
    Replies: 6
    Last Post: 06-10-2006, 08:56 AM
  4. <Gulp>
    By kryptkat in forum Windows Programming
    Replies: 7
    Last Post: 01-14-2006, 01:03 PM
  5. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM