You are not logged in.
I seem to be doing something wrong. I get the output I want without seeding, which is a number 65~90 (A~Z). I want to seed rand, so I can run multiple times with different output, however my seeding is producing the same random number every time. What am I doing wrong here?
char getRandomUpper(){
int upperlimit = 90;
int lowerlimit = 65;
int randomnumber;
srand(time(NULL));
do
{
randomnumber = 1+(rand()%upperlimit);
}
while (randomnumber > upperlimit || randomnumber < lowerlimit);
return (toupper(randomnumber));
}
Last edited by Google (2010-07-31 12:33:07)
Offline
Do not use rand(). Read man 3 random
Offline
Offline
See function srand()
Offline
and if your program is only supposed to run on unix like systems, simply read /dev/urandom
and even if its mission critical...read /dev/random although it will lock if it ran out of entropy... hence...urandom
Offline
Also, try removing the useless loop and toupper() call .
Offline
...and note that it might be a bad idea to use % on the result of rand(), because with some implementations you will end up with a repeating string of numbers (like 0, 1, 0, 1, etc. for rand()%2.)
One alternative involves dividing by RAND_MAX and stuff... Something like
rand() / (RAND_MAX/(upperlimit-lowerlimit))
(but this is not exactly right...)
Edit: I think this should work better:
rand() / (RAND_MAX/(upperlimit-lowerlimit+1)+1)
Last edited by stqn (2010-07-30 12:14:28)
Offline
and if your program is only supposed to run on unix like systems, simply read /dev/urandom
and even if its mission critical...read /dev/random although it will lock if it ran out of entropy... hence...urandom
If it's mission critical, you should be using /dev/random to seed a cryptographically secure (P)RNG. That way you don't tap all your entropy in one go. Or get a hardware RNG.
rand() has lower bit cycles. Stick to srandom() and random(). If you need cross-platform, this would be a good time for wrappers and #ifdef-ing.
Offline
rand() is fine for low-grade random numbers, like those used for rolling dice in games of chance, or shuffling cards, or avoiding certain types of collisions, or most Monte Carlo analysis. It's only if you're doing cryptography that the inherent non-randomness becomes an issue. There's no need to read /dev/random or /dev/urandom unless you have reason to be concerned that people will try to break your security by guessing at the seed of your PRNG.
Many applications demanding "randomness" really only require that patterns "look" random, not that they be generated by an algorithm that can be rigorously proven random by the mathematical definition. Even a crappy PRNG will work for such problems.
Offline
Seeding worked in main (outside of the function). It works nicely but seems like the first value is always the same, but the remaining values are always 'random.' The program doesn't call for a lot of randomness, as long as it appears random it's ok. I had no idea random number generation was such a deep topic until I started this haha.
I am trying to understand why toupper() isn't needed to return a character. Can someone explain? Is it because the function returns a character so the int value is interpreted as a character by the compiler, or is it because during a print you can cast it as "%c" and the int value is interpreted as a character?
I just want to understand everything
Offline
Basically, what toupper() does is, if you give it a number between 'a' and 'z', it will convert it to the same letter in the 'A'..'Z' range. This is not needed since your letter is already in that range, thus the only thing toupper() does for you is indeed convert your int to a char. You can do this more quickly with a simple cast.
(And indeed if the only thing you want to do with this char is printf() it, you can also let it be an int because it will be converted to an int anyway when it is passed to printf().)
Last edited by stqn (2010-07-31 11:14:32)
Offline
So where does the cast actually occur? I tested with ints and I noticed you can cast during the printf with "%c" but does having a function with return type 'char' cast it when the the int is returned?
For example:
char letterA();
char letterA(){
return (65);
}
Will this return A or does it return 65, and the cast only occurs when you cast during the
printf like this:
printf("%c", letterA());
(These are just examples I made here, and are not connected with my program. I just want to understand exactly when the casts happen, or when they can happen.)
I know I seem to be nit picking, but I am trying to understand every detail. I hate doing things without knowing exactly what they do, so I am trying to learn everything.
Last edited by Google (2010-07-31 11:27:00)
Offline
It is incorrect to write "char letterA();" in C, you should write "char letterA(void);".
You don't need to add parentheses after return.
'A' and 65 are the same thing.
Have you got and read a C programming book?
Offline
I am familiar with C++ mostly, but now learning C. I am reading the K&R book for C.
I do understand ascii values and characters etc, but I am trying to understand how the actual compiler/interpreter/language works rather than the syntax itself.
Thanks for your help!
Offline
It is incorrect to write "char letterA();" in C, you should write "char letterA(void);".
Not incorrect, just not best. When you can, you should always prototype functions.
You don't need to add parentheses after return.
True, and although some people do, I think it's unnecessary and annoying.
'A' and 65 are the same thing.
'A' == 65 is true only on certain systems. That assumption is not portable and you should not rely on it. However, even when the assumption holds, 'A' has type char, whereas 65 has type int, so they are not (strictly speaking) interchangeable. But that's beside the point...
When you pass trailing arguments into a variadic function (like printf), a set of promotions occur known as the "default argument promotions" [C99 standard; 6.5.2.2p7]. What this means for printf is that any char or short argument gets promoted to int before it is passed to the function.
printf("%c", 65); /* is the same as */ printf("%c", 'A');
Similarly, any float argument is promoted to double. (These promotions do not take place when you pass (say) a char to a function with a prototype that expects char.) When printf receives the value, it is "already" an int. Conversion specifiers decide what conversions take place within printf.
The printf function converts the int argument to a char before printing it [7.19.6.1p8]. As long as the int has a value that can be represented in a char, the behavior is well-defined.
In your example (slightly modified)
char letterA(void) { return 'A'; } /* function definition */
int main(void) {
printf("%c\n", letterA());
}
the return value of letterA is of type char. It is "promoted" to int before passing to printf. Then printf "converts" that value back to char prior to printing it.
If you really want to get nitpicky, lurk in comp.lang.c and pick up a copy of the C99 Standard (ISO/IEC 9899:1999 TC3; search the Web for n1256.pdf). K&R2 is a great introduction to C (although it predates C99); stick with it.
As an aside: A "cast" is an operator that forces an explicit conversion to some type. Argument promotions are not casts; they are implicit conversions.
Offline
Ah well, what I really meant is that returning 'A' or returning 65 is the same thing . (In answer to his simple example « return (65); ».)
Though I guess it could happen that a non-optimising compiler would convert 'A' to an int or 65 to a char at runtime instead of compile-time... But it doesn't seem to be the case with gcc on x86 at least:
int main()
{
return 'A';
}
compiled with « gcc -O0 -S test.c », produces this asm code:
main:
pushl %ebp
movl %esp, %ebp
movl $65, %eax
popl %ebp
ret
I have no experience of x86 asm, but it seems that 65 is pushed directly as a 32 bits value into eax, without any runtime conversion.
The function:
char letter()
{
return 65;
}
also produces the exact same asm code.
And I'm surprised gcc doesn't give any warning for the missing « void » in the function definitions... I thought it was required. Oh well.
Offline
There's nothing wrong with returning a character from a function that is stated to return int. The other way around, on the other hand, has potential to break things.
char myFunc(void)
{
int ch = 665; /* probably not within the range of a char */
char rv = ch; /* implementation defined */
return rv;
}
-Wconversion turns on warnings for such carelessness.
Offline
rand() is fine for low-grade random numbers, like [...] most Monte Carlo analysis.
Aside from this, I can agree fully. Though, whether or not rand() is sufficient for an MC algorithm would depend on the problem, having quality random numbers seems like a crucial aspect. Maybe not crypto quality, but I think better than rand() can produce. Having random() available as (basically) a drop in replacement with improved "radnomness" would appear to be a no-brainer here.
Offline
Thanks Trent, that is exactly the kind of nitpicky thing I was looking for
Offline
Trent wrote:rand() is fine for low-grade random numbers, like [...] most Monte Carlo analysis.
Aside from this, I can agree fully. Though, whether or not rand() is sufficient for an MC algorithm would depend on the problem, having quality random numbers seems like a crucial aspect. Maybe not crypto quality, but I think better than rand() can produce. Having random() available as (basically) a drop in replacement with improved "radnomness" would appear to be a no-brainer here.
There may be something in what you say. I was considering leaving off MC from the list. Perhaps I should have. It still doesn't require cryptographically secure randomness, which is what I was getting at.
FWIW, I can reliably approximate pi to 2 decimal places using rand() and MC analysis in 0.1 second.
Offline