Velocity Reviews > a gift for the mortensens

# a gift for the mortensens

frank
Guest
Posts: n/a

 01-12-2010
Ben Bacarisse wrote:

>> 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.

Is gcc one of them?

dan@dan-desktop:~/source\$ gcc -std=c99 -Wall -Wextra mort3.c -o out; ./out
mort3.c: In function ‘main’:
mort3.c:12: warning: unused variable ‘c’
/tmp/ccAPcgbE.o: In function `main':
mort3.c.text+0x5: undefined reference to `nextafter'
collect2: ld returned 1 exit status
bash: ./out: No such file or directory
dan@dan-desktop:~/source\$ cat mort3.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <math.h>

#define N 26

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

srand(time(NULL));
printf ("RAND_MAX is %d\n", RAND_MAX);
i = nextafter((double)rand() / RAND_MAX, 0);
printf ("i is %d\n", i);

return 0;
}

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

frank
Guest
Posts: n/a

 01-12-2010
Keith Thompson wrote:
> 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.

Now that I think about it, you are absolutely correct. i assumes one
value in the program and hence cannot be two. I think I was injecting
less belief in the "i is " part than a literal one. A longer version of
it may have been better to read "The integer I'm looking for is ".
>
>>>> 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.
>

I swear I've seen it differently, but I doubt you'd write that if it
weren't demonstrable.
>
>> 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>).

For something like this, I don't want to write a program; I want to look
at limits.h for my implementation. I've probably asked you three times
for this over the past couple years, but I keep getting sent back to go
in a lot of ways, as I work up my linux install for the 4th time. What
is the name of the newsgroup specific to gcc?
--
frank

frank
Guest
Posts: n/a

 01-12-2010
Keith Thompson wrote:
> 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.

I think "we" should update the FAQ to replace your expression with the
one that Steve Summit had. People like me, who read his collection
while sitting in a parking lot, are always grateful for his
contribution, but useless casts make code unreadable.
>
> [...]
>> #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.

Yeah, I didn't do the best editing here.
>
>
> 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.
>

http://clc-wiki.net/wiki/clc-wikiolicies#codeformat

This is topical, according to the wiki. I didn't explain the details
but will now take the opportunity to do so. MY OS (ubuntu) registered
that I wanted indent and gave me the the line that I needed to make it
happen off the command line. Then I hit the up arrow twice to find the
command that had failed, and voila.
--
frank

Barry Schwarz
Guest
Posts: n/a

 01-12-2010
On Mon, 11 Jan 2010 15:14:23 -0800, Keith Thompson <(E-Mail Removed)>
wrote:

>frank <(E-Mail Removed)> writes:

snip

>> #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.
>
>
> 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.

Only the second cast to double is necessary. Once RAND_MAX is
converted to double, all the remaining values in the expression must
also be converted. While the first cast to double might achieve the
same effect, the denominator would be evaluated as an int first and
could overflow before being converted to double.

--
Remove del for email

Barry Schwarz
Guest
Posts: n/a

 01-12-2010
On Mon, 11 Jan 2010 16:26:52 -0700, frank <(E-Mail Removed)>
wrote:

>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.

The character '1' on an ASCII system is 0x31. On an EBCDIC system it
is 0xF1. ASCII 'A' is 0x41, EBCDIC is 0xC1. Worse, on an ASCII
system, 'J'-'I' is 1; in EBCDIC it is 8.

About the only character in common is '\0' which is 0x00 on both.

--
Remove del for email

Keith Thompson
Guest
Posts: n/a

 01-12-2010
frank <(E-Mail Removed)> writes:
> Ben Bacarisse wrote:

[...]
>> 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.

>
> Is gcc one of them?

No, since gcc is a compiler not a library. (glibc is the library
most commonly associated with gcc, but in fact gcc is generally
used with whatever library exists on the system.)

[...]

--
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"

Keith Thompson
Guest
Posts: n/a

 01-12-2010
frank <(E-Mail Removed)> writes:
> Keith Thompson wrote:
>> frank <(E-Mail Removed)> writes:
>>> Barry Schwarz wrote:
>>>> On Sun, 10 Jan 2010 16:05:14 -0700, frank <(E-Mail Removed)>
>>>> wrote:

[...]
>>>>> 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.

>
> Now that I think about it, you are absolutely correct. i assumes one
> value in the program and hence cannot be two. I think I was injecting
> less belief in the "i is " part than a literal one. A longer version
> of it may have been better to read "The integer I'm looking for is ".

So you were using "i" to refer generically to whatever integer you're
looking at the moment, while your program declares an integer object
named "i". That's, um, a very interesting way of looking at things.

Really, given that you wanted to display the values of i and RAND_MAX,
the only sensible thing to write would be:

printf("i is %d\n", i);
printf("RAND_MAX is %d\n", RAND_MAX);

or some variation.

[...]

>>> 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>).

>
> For something like this, I don't want to write a program; I want to
> look at limits.h for my implementation.

Ok, nobody's stopping you. But why? The standard headers aren't
generally written to be particularly human-readable. On my system,
for example, I see the following in /usr/include/limits.h:

/* Minimum and maximum values a `char' can hold. */
# ifdef __CHAR_UNSIGNED__
# define CHAR_MIN 0
# define CHAR_MAX UCHAR_MAX
# else
# define CHAR_MIN SCHAR_MIN
# define CHAR_MAX SCHAR_MAX
# endif

I can guess where __CHAR_UNSIGNED__ would be defined, but I'm not sure
(plain char is signed on my system).

For that matter, the standard headers aren't necessarily even
implemented as source files.

Writing and executing a program is the only reliable way to display
the values to which these macros expand.

> I've probably asked you three
> times for this over the past couple years, but I keep getting sent
> back to go in a lot of ways, as I work up my linux install for the 4th
> time. What is the name of the newsgroup specific to gcc?

You're probably looking for gnu.gcc.help.

--
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"

Keith Thompson
Guest
Posts: n/a

 01-12-2010
frank <(E-Mail Removed)> writes:
> Keith Thompson wrote:
>> 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.

>
> I think "we" should update the FAQ to replace your expression with the
> one that Steve Summit had.

I think you meant that the other way around.

> People like me, who read his collection
> while sitting in a parking lot, are always grateful for his
> contribution, but useless casts make code unreadable.

What useless casts? There were several in the earlier code you
posted; there aren't very many in the FAQ. In question 13.16, we see:

(int)((double)rand() / ((double)RAND_MAX + 1) * N)

and

(int)(drand48() * N)

The double casts *are* necessary. The int casts may or may not be,
depending on what's done with the result.

[...]

>>
>> 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.

>
> http://clc-wiki.net/wiki/clc-wikiolicies#codeformat
>
> This is topical, according to the wiki.

[l..]

the point any further would just be ironic.

--
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"

Keith Thompson
Guest
Posts: n/a

 01-12-2010
Richard Heathfield <(E-Mail Removed)> writes:
> Barry Schwarz wrote:
>> On Mon, 11 Jan 2010 15:14:23 -0800, Keith Thompson <(E-Mail Removed)>
>> wrote:

>
> <snip>
>
>>>
>>> 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.

>>
>> Only the second cast to double is necessary.

>
> Not even the second cast is necessary.
>
> i = (rand() / (RAND_MAX + 1.0)) * N;

Nicely done!

In cases like this, though, I think I'd argue that using casts or not
is largely a matter of taste. I find that I'm a little uncomfortable
with the way the constant 1.0 imposes its type on the rest of the
expression, bubbling up through multiple levels of the tree.

And I suppose that's inconsistent with most of what I've said about
using casts where implicit conversions would do the same job. Oh,
well.

--
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"

Ben Bacarisse
Guest
Posts: n/a

 01-12-2010
frank <(E-Mail Removed)> writes:

> Ben Bacarisse wrote:

<snip>
>> ... 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.

>
> Is gcc one of them?

glibc (rather than gcc) includes drand48. It is a POSIX function.

<snip>
--
Ben.