# portable random function: can someone explain it?

Show 80 post(s) from this thread on one page
Page 1 of 2 12 Last
• 05-14-2009
fsx
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.

Code:

```    {         time_t t = time(NULL);         while (t > 0u - 1 + 0.0) {             t /= 2;         }         srand(t);     }```
• 05-14-2009
matsp
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
• 05-14-2009
MK27
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.

 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...
• 05-14-2009
MK27
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?
• 05-14-2009
fsx
Quote:

Originally Posted by MK27
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?
• 05-14-2009
MK27
Quote:

Originally Posted by fsx
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.
• 05-14-2009
matsp
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
• 05-14-2009
Snafuist
Quote:

Originally Posted by MK27
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.
• 05-14-2009
MK27
Quote:

Originally Posted by Snafuist
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.
• 05-14-2009
Brafil
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.
• 05-14-2009
Snafuist
Quote:

Originally Posted by MK27
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
• 05-14-2009
MK27
Quote:

Originally Posted by Snafuist
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.
• 05-14-2009
laserlight
Incidentally, I suggest reading Prelude's article on using rand(); she provides another way of seeding with srand() using time() that is portable.
• 05-14-2009
Nyda

Code:

```  time_t t = time(NULL);   while (t > (t & ~0)) {     t /= 2;   }   srand(t);```
I say it works, who says it doesn't ? ;)
• 05-14-2009
laserlight
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.
Show 80 post(s) from this thread on one page
Page 1 of 2 12 Last