Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C Programming > a gift for the mortensens

Reply
Thread Tools

a gift for the mortensens

 
 
frank
Guest
Posts: n/a
 
      01-11-2010
Keith Thompson wrote:
> frank <(E-Mail Removed)> writes:


[snipped and reordered for thematic reasons]

> None of the three casts in your program are necessary, and IMHO your
> code would be improved by dropping them.
>
> srand(time(NULL);;
> ...
> c = i;


This seems to work (with a right paren added and semi-colon removed):

dan@dan-desktop:~/source$ gcc -std=c99 -Wall -Wextra mort2.c -o out; ./out
mort2.c: In function ‘main’:
mort2.c:11: warning: unused variable ‘c’
RAND_MAX is 2147483647
i is 13
dan@dan-desktop:~/source$ cat mort2.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define N 26

int
main (void)
{
int i;
char c;

srand(time(NULL));
printf ("RAND_MAX is %d\n", RAND_MAX);
i = (int) ((double) rand () / ((double) RAND_MAX + 1) * N);
printf ("i is %d\n", i);

return 0;
}

// gcc -std=c99 -Wall -Wextra mort2.c -o out; ./out
dan@dan-desktop:~/source$

So none of those casts were doing anything for me? If so, I say we
replace this part of the FAQ.


>
> The second "i is %d\n" presumably is a typo for "RAND_MAX is %d\n".
>


more or less
> If plain char is signed, the conversion of i from int to char (which
> occurs with or without the cast) can produce an implementation-defined
> result or raise an implementation-defined signal. If you want to
> produce numbers within a specified range, you should do the necessary
> arithmetic yourself.


ok
>
> If you want random lowercase letters, you can declare
>
> const char letters[] = "abcdefghijklmnopqrstuvwxyz"
>
> and index into the array with a random number in the range 0..25.
>
> Section 13 of the comp.lang.c FAQ, <http://www.c-faq.com/>, has
> several questions about random numbers.
>


ok

> Indentation?
>


[implementation-specific]
I love these utilities that I get from ubuntu:
dan@dan-desktop:~/source$ indent -i3 mort2.c
The program 'indent' is currently not installed. You can install it by
typing:
sudo apt-get install indent
bash: indent: command not found
dan@dan-desktop:~/source$ sudo apt-get install indent
[sudo] password for dan:
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following packages were automatically installed and are no longer
required:
linux-headers-2.6.28-11 linux-headers-2.6.28-11-generic
Use 'apt-get autoremove' to remove them.
The following NEW packages will be installed:
indent
0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded.
Need to get 81.4kB of archives.
After this operation, 508kB of additional disk space will be used.
Get:1 http://us.archive.ubuntu.com jaunty/main indent 2.2.10-1 [81.4kB]
Fetched 81.4kB in 1s (41.4kB/s)
Selecting previously deselected package indent.
(Reading database ... 122566 files and directories currently installed.)
Unpacking indent (from .../indent_2.2.10-1_i386.deb) ...
Processing triggers for man-db ...
Setting up indent (2.2.10-1) ...

dan@dan-desktop:~/source$ indent -i3 mort2.c
dan@dan-desktop:~/source$ cat mort2.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

#define N 26

int
main (void)
{
int i;
char c;

srand ((unsigned int) time ((time_t *) NULL));
printf ("RAND_MAX is %d\n", RAND_MAX);
i = (int) ((double) rand () / ((double) RAND_MAX + 1) * N);
printf ("i is %d\n", i);

return 0;
}

// gcc -std=c99 -Wall -Wextra mort2.c -o out; ./out

It took less than a minute.
--
frank


 
Reply With Quote
 
 
 
 
Keith Thompson
Guest
Posts: n/a
 
      01-11-2010
frank <(E-Mail Removed)> writes:
> Keith Thompson wrote:
>> frank <(E-Mail Removed)> writes:

>
> [snipped and reordered for thematic reasons]
>
>> None of the three casts in your program are necessary, and IMHO your
>> code would be improved by dropping them.
>>
>> srand(time(NULL);;
>> ...
>> c = i;

>
> This seems to work (with a right paren added and semi-colon removed):


Oops, typo on my part.

[...]
> #include <stdio.h>
> #include <stdlib.h>
> #include <time.h>
>
> #define N 26
>
> int
> main (void)
> {
> int i;
> char c;
>
> srand(time(NULL));
> printf ("RAND_MAX is %d\n", RAND_MAX);
> i = (int) ((double) rand () / ((double) RAND_MAX + 1) * N);
> printf ("i is %d\n", i);
>
> return 0;
> }
>
> // gcc -std=c99 -Wall -Wextra mort2.c -o out; ./out
> dan@dan-desktop:~/source$
>
> So none of those casts were doing anything for me? If so, I say we
> replace this part of the FAQ.


No, that's not what I said. None of the casts in your previous code
were necessary. I obviously wasn't commenting on code you hadn't
posted yet.

In your new code:

i = (int) ((double) rand () / ((double) RAND_MAX + 1) * N);

the cast to int is unnecessary, since the result is being assigned to
an int object. The other two casts are necessary and appropriate,
since in their absence the int values wouldn't be converted to double.

[...]

>> Indentation?
>>

>

[52 lines deleted]
>
> It took less than a minute.


Great. Though I'm not quite sure why you felt the need to tell us, in
great detail, how you did it. Just posting properly indented code is
more than enough.

--
Keith Thompson (The_Other_Keith) http://www.velocityreviews.com/forums/(E-Mail Removed) <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
 
 
 
frank
Guest
Posts: n/a
 
      01-11-2010
Ben Bacarisse wrote:
> frank <(E-Mail Removed)> writes:
> <snip>
>> What I want to do now is produce equiprobable chars. If I wanted all
>> the chars, then I think that the above would suffice, but I want only
>> lower case letters.
>>
>> I could use j = rand()%26 or some such and add that character to a,
>> but I want to be mindful of 13.16, which warns against this. Can
>> someone say a few words about this?

>
> When RAND_MAX is 2147483647 (as in your example) rand() results from 0
> up to 2147483623 give you remainders 0 to 25 repeatedly. In fact
> there are 82595524 sets of remainders. The 24 "left over" numbers,
> 2147483624 to 2147483647, give remainders 0 to 23 so, on average, 24
> and 25 occur very slightly less often (1 in 82595525 times). The bias
> is tiny -- will it matter?
>
> If it does matter, instead of calling rand() once you must loop until
> the result is between 0 and 2147483623. To be portable you'd write:
>
> int r;
> while ((r = rand()) >= RAND_MAX/26);
>


I don't quite see what you mean here, Ben. As I evaluate this, I start
at the right and get a number that is about a hundred million, and I
don't see how your source equates to its description.

What I think we need to do with this method is toss out all the results
higher than ...23 . If your source does this, can you tell me how?
--
frank
 
Reply With Quote
 
frank
Guest
Posts: n/a
 
      01-11-2010
Barry Schwarz wrote:
> On Sun, 10 Jan 2010 16:05:14 -0700, frank <(E-Mail Removed)>
> wrote:


>> dan@dan-desktop:~/source$ gcc -std=c99 -Wall -Wextra mort1.c -o out; ./out
>> i is 1337295409
>> i is 2147483647

>
> One of these statements must be false.


They are not simultaneously, but sequentially true.
>
>> c is 1

>
> While that is the character representation of low order byte on an
> ASCII machine, my EBCDIC system will produce significantly different
> output.


I thought they were the same for the first 128 elements, and that ascii
filled out 129-256, while ebcdic was size 128.

snip
>> c=(char)i;

>
> Does your system complain without the cast? If this code is executed
> on a system where char is signed, the cast may not produce the desired
> value and may not produce any value.


Why would a person want to have a signed char? I've never used one,
except errantly.

snip
--
frank
 
Reply With Quote
 
Ben Bacarisse
Guest
Posts: n/a
 
      01-11-2010
frank <(E-Mail Removed)> writes:
<snip>
> dan@dan-desktop:~/source$ cat mort2.c
> #include <stdio.h>
> #include <stdlib.h>
> #include <time.h>
>
> #define N 26
>
> int
> main (void)
> {
> int i;
> char c;
>
> srand(time(NULL));
> printf ("RAND_MAX is %d\n", RAND_MAX);
> i = (int) ((double) rand () / ((double) RAND_MAX + 1) * N);


Here be dragons. As 64 bit integers get more and more common we are
edging towards a time when this will routinely fail because
(double)RAND_MAX + 1 can be equal to RAND_MAX if RAND_MAX is big
enough. This does not happen with a 32 RNG and normal IEEE
double-precision numbers, but if RAND_MAX is big enough (and a signed
64-bit int is big enough) the +1 has no effect on (double)RAND_MAX.

To get a floating-point number in [0, 1) I have taken to writing:

nextafter((double)rand() / RAND_MAX, 0)

nextafter is a C99 function that gives the next representable number,
near the first argument in the direction of the second. There are
probably better ways to do this, but the best of all would be a
floating-point random function in C. Such a function could rely on
the internal representation of a floating point number to give a
properly uniform distribution. Many C libraries include such a
function as an extension.

> printf ("i is %d\n", i);
>
> return 0;
> }


<snip>
--
Ben.
 
Reply With Quote
 
Ben Bacarisse
Guest
Posts: n/a
 
      01-11-2010
frank <(E-Mail Removed)> writes:

> Ben Bacarisse wrote:
>> frank <(E-Mail Removed)> writes:
>> <snip>
>>> What I want to do now is produce equiprobable chars. If I wanted all
>>> the chars, then I think that the above would suffice, but I want only
>>> lower case letters.
>>>
>>> I could use j = rand()%26 or some such and add that character to a,
>>> but I want to be mindful of 13.16, which warns against this. Can
>>> someone say a few words about this?

>>
>> When RAND_MAX is 2147483647 (as in your example) rand() results from 0
>> up to 2147483623 give you remainders 0 to 25 repeatedly. In fact
>> there are 82595524 sets of remainders. The 24 "left over" numbers,
>> 2147483624 to 2147483647, give remainders 0 to 23 so, on average, 24
>> and 25 occur very slightly less often (1 in 82595525 times). The bias
>> is tiny -- will it matter?
>>
>> If it does matter, instead of calling rand() once you must loop until
>> the result is between 0 and 2147483623. To be portable you'd write:
>>
>> int r;
>> while ((r = rand()) >= RAND_MAX/26);
>>

>
> I don't quite see what you mean here, Ben. As I evaluate this, I
> start at the right and get a number that is about a hundred million,
> and I don't see how your source equates to its description.


Yes, I made a mistake. I meant to write:

while ((r = rand()) >= (RAND_MAX/26)*26);

(I hope I've got that right now.) This should discard the 24 extra
results that lead to the bias.

This may be moot now since from your recent post I think you have
decided that the bias does not matter.

--
Ben.
 
Reply With Quote
 
Keith Thompson
Guest
Posts: n/a
 
      01-11-2010
frank <(E-Mail Removed)> writes:
> Barry Schwarz wrote:
>> On Sun, 10 Jan 2010 16:05:14 -0700, frank <(E-Mail Removed)>
>> wrote:

>
>>> dan@dan-desktop:~/source$ gcc -std=c99 -Wall -Wextra mort1.c -o out; ./out
>>> i is 1337295409
>>> i is 2147483647

>>
>> One of these statements must be false.

>
> They are not simultaneously, but sequentially true.


As I already pointed out and you acknowledged, the second "i is" was a
typo for "RAND_MAX is". i never takes on the value 2147483647, except
perhaps by coincidence. As printed, the first statement is true, the
second is false.

>>> c is 1

>>
>> While that is the character representation of low order byte on an
>> ASCII machine, my EBCDIC system will produce significantly different
>> output.

>
> I thought they were the same for the first 128 elements, and that
> ascii filled out 129-256, while ebcdic was size 128.


Nope. ASCII is a 7-bit code with codes 0-127 (typically stored in an
8-bit byte). EBCDIC is an 8-bit code, mostly inconsistent with ASCII.

Google is your friend.

> snip
>>> c=(char)i;

>>
>> Does your system complain without the cast? If this code is executed
>> on a system where char is signed, the cast may not produce the desired
>> value and may not produce any value.

>
> Why would a person want to have a signed char? I've never used one,
> except errantly.


Historical reasons, mostly. The point is that, on many modern
implementations, very likely including the one you're using, plain
char is a signed type.

Try printing the values of CHAR_MIN, CHAR_MAX, SCHAR_MIN, SCHAR_MAX,
and UCHAR_MAX (defined in <limits.h>).

--
Keith Thompson (The_Other_Keith) (E-Mail Removed) <http://www.ghoti.net/~kst>
Nokia
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
 
Reply With Quote
 
frank
Guest
Posts: n/a
 
      01-12-2010
Ben Bacarisse wrote:

> Yes, I made a mistake. I meant to write:
>
> while ((r = rand()) >= (RAND_MAX/26)*26);
>
> (I hope I've got that right now.) This should discard the 24 extra
> results that lead to the bias.


That makes sense now.
>
> This may be moot now since from your recent post I think you have
> decided that the bias does not matter.
>


Does the following admit of the same bias:
i = ((double) rand () / ((double) RAND_MAX + 1) * N);

What's happening bitwise in the above?
--
frank
 
Reply With Quote
 
Ersek, Laszlo
Guest
Posts: n/a
 
      01-12-2010
In article <0.e39a1a19d064e8d97c6e.20100111233939GMT.87my0kmc (E-Mail Removed)>, Ben Bacarisse <(E-Mail Removed)> writes:

> To get a floating-point number in [0, 1)


"The drand48() and erand48() functions shall return non-negative,
double-precision, floating-point values, uniformly distributed over the
interval [0.0,1.0)."

Not standard C, but present in SUS since v1. [0] [1] [2]

erand48() should be suitable for multi-threaded usage. [3] [4] [5]

The XSI legend in SUSv4 [0] and SUSv3 [1] only shows that the interface
is not required from the implementation for POSIX conformance, but
required for XSI (X/Open System Interfaces or Single UNIX Specification)
conformance [6] [7].

Cheers,
lacos

[0] http://www.opengroup.org/onlinepubs/...s/drand48.html
[1] http://www.opengroup.org/onlinepubs/...s/drand48.html
[2] http://www.opengroup.org/onlinepubs/...h/drand48.html

[3] http://www.opengroup.org/onlinepubs/...l#tag_15_09_01
[4] http://www.opengroup.org/onlinepubs/...l#tag_02_09_01
[5] http://www.opengroup.org/onlinepubs/...ag_000_010_002

[6] http://www.opengroup.org/onlinepubs/...tml#tag_03_442
[7] http://www.opengroup.org/onlinepubs/...tml#tag_03_439
 
Reply With Quote
 
Ben Bacarisse
Guest
Posts: n/a
 
      01-12-2010
frank <(E-Mail Removed)> writes:
<snip>
> Does the following admit of the same bias:
> i = ((double) rand () / ((double) RAND_MAX + 1) * N);


Yes.

> What's happening bitwise in the above?


That's complex and not very helpful, I think. The simplest way to see
what is happening is to pretend RAND_MAX is, say, 15 and to run through
all the outcomes when N does not divide 16. You'll see that some values
(2, 4 and 7) occur less frequently than the rest.

--
Ben.
 
Reply With Quote
 
 
 
Reply

Thread Tools

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 On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Special Gift Gift Idea using Your Photo! emyface2@hotmail.com Digital Photography 0 04-03-2006 11:07 AM
OT: Gift? Kat MCSE 11 03-11-2005 09:23 PM
Fill out a short survey and win $100 gift certificate. jilp Cisco 0 11-24-2003 06:01 PM
OT gift ideas? Consultant MCSE 1 10-22-2003 12:36 AM
Re: A Gift for the MCSE that has everything Kendal Emery MCSE 1 08-01-2003 02:45 AM



Advertisments