a gift for the mortensens

Discussion in 'C Programming' started by frank, Jan 10, 2010.

  1. frank

    frank Guest

    Christmas persists for me. If you ever get an opportunity to attend a
    "white elephant party," do so, because it's hilarious.

    My friend Alan Mortensen forbade me from spending money on gifts as I
    visited his and my family in Salt lake over the actual holidays, so I'm
    working out a way where I can give his girls something of value.

    I intend to write a couple C utilities for them, as software is not
    dough. Where I'm stuck right now is that I can't seem to find source
    for invoking pseudo-random behaviour. So here's my first attempt:

    #include <stdio.h>
    #include <stdlib.h>

    int main (void)
    {

    void srand(unsigned seed);
    int rand(void);
    time_t time(something);

    srand(time(&timer));

    return("pretty pathetic");
    }

    I've written hundreds of programs in C that invoke pseudo-random
    behavior but nothing recently, or as "frank."

    So, I'm looking for a link or some tips on how to invoke pseudo-random
    behavior in C. Thanks for your comment.
    --
    frank
    frank, Jan 10, 2010
    #1
    1. Advertising

  2. On 10 Jan, 07:35, frank <> wrote:

    > I intend to write a couple C utilities [...].  
    > Where I'm stuck right now is that I can't seem to find source
    > for invoking pseudo-random behaviour.  So here's my first attempt:
    >
    > #include <stdio.h>
    > #include <stdlib.h>
    >
    > int main (void)
    > {
    >
    > void srand(unsigned seed);
    > int rand(void);


    don't do this. It isn't necessary if you have the approriate #includes


    > time_t time(something);
    >
    > srand(time(&timer));
    >
    > return("pretty pathetic");
    >
    > }
    >
    > I've written hundreds of programs in C that invoke pseudo-random
    > behavior but nothing recently, or as "frank."
    >
    > So, I'm looking for a link or some tips on how to invoke pseudo-random
    > behavior in C.  Thanks for your comment.


    try the FAQ http://c-faq.com/lib/index.html
    particularly questions 13.15 and 13.16
    Nick Keighley, Jan 10, 2010
    #2
    1. Advertising

  3. frank

    frank Guest

    Nick Keighley wrote:
    > On 10 Jan, 07:35, frank <> wrote:
    >
    >> I intend to write a couple C utilities [...].
    >> Where I'm stuck right now is that I can't seem to find source
    >> for invoking pseudo-random behaviour. So here's my first attempt:
    >>
    >> #include <stdio.h>
    >> #include <stdlib.h>
    >>
    >> int main (void)
    >> {
    >>
    >> void srand(unsigned seed);
    >> int rand(void);

    >
    > don't do this. It isn't necessary if you have the approriate #includes


    right. They're already declared in the headers.

    > try the FAQ http://c-faq.com/lib/index.html
    > particularly questions 13.15 and 13.16
    >


    The FAQ wouldn't load but I have a hard copy here that gave me what
    seems to be an appropriate seed:

    dan@dan-desktop:~/source$ gcc -std=c99 -Wall -Wextra mort1.c -o out; ./out
    i is 1337295409
    i is 2147483647
    c is 1
    dan@dan-desktop:~/source$ ./out
    i is 1660238507
    i is 2147483647
    c is �
    dan@dan-desktop:~/source$ cat mort1.c
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>

    int main(void)
    {


    int i;
    char c;
    srand((unsigned int)time((time_t *)NULL));

    i=rand();
    printf("i is %d\n", i);
    printf("i is %d\n", RAND_MAX);
    c=(char)i;
    printf("c is %c\n", c);

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

    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?

    TIA.
    --
    frank
    frank, Jan 10, 2010
    #3
  4. On Sun, 10 Jan 2010 16:05:14 -0700, frank <>
    wrote:

    snip

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

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

    >dan@dan-desktop:~/source$ ./out
    >i is 1660238507
    >i is 2147483647
    >c is ?
    >dan@dan-desktop:~/source$ cat mort1.c
    >#include <stdio.h>
    >#include <stdlib.h>
    >#include <time.h>
    >
    >int main(void)
    >{
    >
    >
    >int i;
    >char c;
    >srand((unsigned int)time((time_t *)NULL));
    >
    >i=rand();
    >printf("i is %d\n", i);
    >printf("i is %d\n", RAND_MAX);


    This statement is rarely true. For some seeds, it need not ever be
    true.

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

    >printf("c is %c\n", c);
    >
    >return 0;
    >}
    >// gcc -std=c99 -Wall -Wextra mort1.c -o out; ./out
    >dan@dan-desktop:~/source$
    >
    >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?


    There is no requirement for rand to produce random numbers with a
    uniform distribution. How will your code handle a normal or Poisson
    distribution?

    --
    Remove del for email
    Barry Schwarz, Jan 10, 2010
    #4
  5. frank <> 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);

    --
    Ben.
    Ben Bacarisse, Jan 10, 2010
    #5
  6. Barry Schwarz <> writes:
    [...]
    > There is no requirement for rand to produce random numbers with a
    > uniform distribution. How will your code handle a normal or Poisson
    > distribution?


    The standard's requirement is (C99 7.20.2.1p2):

    The rand function computes a sequence of pseudo-random integers in
    the range 0 to RAND_MAX.

    I've always assumed that this is meant to imply a uniform
    distribution. The authors probably thought that was so obvious it
    didn't need to be stated.

    Of course, any finite sequence from a uniform distribution has a
    finite probability of looking like a normal or Poisson distribution,
    or even a sequence of 0s.

    --
    Keith Thompson (The_Other_Keith) <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, Jan 11, 2010
    #6
  7. frank <> writes:
    [..]
    > #include <stdio.h>
    > #include <stdlib.h>
    > #include <time.h>
    >
    > int main(void)
    > {
    >
    >
    > int i;
    > char c;
    > srand((unsigned int)time((time_t *)NULL));
    >
    > i=rand();
    > printf("i is %d\n", i);
    > printf("i is %d\n", RAND_MAX);
    > c=(char)i;
    > printf("c is %c\n", c);
    >
    > return 0;
    > }


    Indentation?

    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;

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

    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.

    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.

    --
    Keith Thompson (The_Other_Keith) <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, Jan 11, 2010
    #7
  8. On 10 Jan, 23:05, frank <> wrote:
    > Nick Keighley wrote:
    > > On 10 Jan, 07:35, frank <> wrote:


    > >> I intend to write a couple C utilities [...].  
    > >> Where I'm stuck right now is that I can't seem to find source
    > >> for invoking pseudo-random behaviour.  So here's my first attempt:


    <snip>

    > > try the FAQhttp://c-faq.com/lib/index.html
    > > particularly questions 13.15 and 13.16

    >
    > The FAQ wouldn't load but I have a hard copy here that gave me what
    > seems to be an appropriate seed:


    <snip>

    > #include <stdio.h>
    > #include <stdlib.h>
    > #include <time.h>
    >
    > int main(void)
    > {
    >
    > int i;
    > char c;
    > srand((unsigned int)time((time_t *)NULL));
    >
    > i=rand();
    > printf("i is %d\n", i);
    > printf("i is %d\n", RAND_MAX);
    > c=(char)i;


    what do you think this does?

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


    <snip>

    > What I want to do now is produce equiprobable chars.


    see FAQ 13.6

    > If I wanted all
    > the chars, then I think that the above would suffice,


    and likely a lot of other stuff

    > but I want only lower case letters.
    >
    > I could use j = rand()%26


    that produces badly distributed numbers in the rnage 0..25. The lower
    case letters are not in the range 0..25 in most character sets. Use
    FAQ 13.6 to get yourself a uniform distribution of numbers in the
    range in the range 0..25. The use Keiths idea or add 'a' (which will
    work for ASCII).

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


    do what 13.6 says?
    Nick Keighley, Jan 11, 2010
    #8
  9. frank

    Frank Guest

    On 1/11/2010 2:35 AM, Nick Keighley wrote:
    > On 10 Jan, 23:05, frank<> wrote:
    >> Nick Keighley wrote:
    >>> On 10 Jan, 07:35, frank<> wrote:

    >
    >>>> I intend to write a couple C utilities [...].
    >>>> Where I'm stuck right now is that I can't seem to find source
    >>>> for invoking pseudo-random behaviour. So here's my first attempt:

    >
    > <snip>
    >
    >>> try the FAQhttp://c-faq.com/lib/index.html
    >>> particularly questions 13.15 and 13.16

    >>
    >> The FAQ wouldn't load but I have a hard copy here that gave me what
    >> seems to be an appropriate seed:

    >
    > <snip>
    >
    >> #include<stdio.h>
    >> #include<stdlib.h>
    >> #include<time.h>
    >>
    >> int main(void)
    >> {
    >>
    >> int i;
    >> char c;
    >> srand((unsigned int)time((time_t *)NULL));
    >>
    >> i=rand();
    >> printf("i is %d\n", i);
    >> printf("i is %d\n", RAND_MAX);
    >> c=(char)i;

    >
    > what do you think this does?


    Wouldn't this be a demotion? Mapping onto a smaller set like modular
    athimetic. It *should* be able to produce any char in the set, and
    somewhat equiprobably.
    >
    >> printf("c is %c\n", c);
    >>
    >> return 0;}

    >
    > <snip>
    >
    >> What I want to do now is produce equiprobable chars.

    >
    > see FAQ 13.6


    I think they've switched numbers on the on-line ones:

    Q: How can I split up a string into whitespace-separated fields?
    How can I duplicate the process by which main() is handed argc and argv?

    >
    >> If I wanted all
    >> the chars, then I think that the above would suffice,

    >
    > and likely a lot of other stuff
    >
    >> but I want only lower case letters.
    >>
    >> I could use j = rand()%26

    >
    > that produces badly distributed numbers in the rnage 0..25. The lower
    > case letters are not in the range 0..25 in most character sets. Use
    > FAQ 13.6 to get yourself a uniform distribution of numbers in the
    > range in the range 0..25. The use Keiths idea or add 'a' (which will
    > work for ASCII).
    >
    >> 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?

    >
    > do what 13.6 says?


    Thanks all for responses. I have to run right now but had source tyo
    discuss.
    --
    frank
    Frank, Jan 11, 2010
    #9
  10. Frank <> writes:
    > On 1/11/2010 2:35 AM, Nick Keighley wrote:
    >> On 10 Jan, 23:05, frank<> wrote:

    [...]
    >>> int i;
    >>> char c;

    [...]
    >>> c=(char)i;

    >>
    >> what do you think this does?

    >
    > Wouldn't this be a demotion? Mapping onto a smaller set like modular
    > athimetic. It *should* be able to produce any char in the set, and
    > somewhat equiprobably.

    [...]

    It's a conversion; since it converts from a wider type to a narrower
    type, I suppose you could call it a demotion.

    But what makes you think modular arithmetic is involved?

    Plain char may be either signed or unsigned. If it's unsigned, then
    yes, the result of the conversion is reduced modulo UCHAR_MAX+1
    (that's modulo 256 on systems with 8-bit bytes). But if it's signed,
    and the int value is outside the range CHAR_MIN..CHAR_MAX, then the
    result of the conversion is implementation-defined -- *or* an
    implementation-defined signal is raised.

    I already mentioned this elsethread, though not in quite so much
    detail.

    --
    Keith Thompson (The_Other_Keith) <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, Jan 11, 2010
    #10
  11. frank

    frank Guest

    Keith Thompson wrote:
    > frank <> 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
    frank, Jan 11, 2010
    #11
  12. frank <> writes:
    > Keith Thompson wrote:
    >> frank <> 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.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, Jan 11, 2010
    #12
  13. frank

    frank Guest

    Ben Bacarisse wrote:
    > frank <> 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
    frank, Jan 11, 2010
    #13
  14. frank

    frank Guest

    Barry Schwarz wrote:
    > On Sun, 10 Jan 2010 16:05:14 -0700, frank <>
    > 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
    frank, Jan 11, 2010
    #14
  15. frank <> 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.
    Ben Bacarisse, Jan 11, 2010
    #15
  16. frank <> writes:

    > Ben Bacarisse wrote:
    >> frank <> 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.
    Ben Bacarisse, Jan 11, 2010
    #16
  17. frank <> writes:
    > Barry Schwarz wrote:
    >> On Sun, 10 Jan 2010 16:05:14 -0700, frank <>
    >> 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) <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, Jan 11, 2010
    #17
  18. frank

    frank Guest

    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
    frank, Jan 12, 2010
    #18
  19. In article <>, Ben Bacarisse <> 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/9699919799/functions/drand48.html
    [1] http://www.opengroup.org/onlinepubs/000095399/functions/drand48.html
    [2] http://www.opengroup.org/onlinepubs/007908775/xsh/drand48.html

    [3] http://www.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_09_01
    [4] http://www.opengroup.org/onlinepubs/000095399/functions/xsh_chap02_09.html#tag_02_09_01
    [5] http://www.opengroup.org/onlinepubs/007908775/xsh/threads.html#tag_000_010_002

    [6] http://www.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap03.html#tag_03_442
    [7] http://www.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap03.html#tag_03_439
    Ersek, Laszlo, Jan 12, 2010
    #19
  20. frank <> 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.
    Ben Bacarisse, Jan 12, 2010
    #20
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Janaka

    Gift vouchers

    Janaka, Aug 24, 2004, in forum: ASP .Net
    Replies:
    6
    Views:
    425
    =?Utf-8?B?Um9zaGFuIEpheWFsYXRo?=
    Sep 23, 2004
  2. Larry Webb

    Printable gift certificates

    Larry Webb, Jan 21, 2006, in forum: HTML
    Replies:
    5
    Views:
    1,331
  3. Mark Bruno
    Replies:
    2
    Views:
    339
  4. Just D.

    Bad Gift from MS in December 2006

    Just D., Jan 10, 2007, in forum: ASP .Net
    Replies:
    2
    Views:
    330
    Just D.
    Jan 10, 2007
  5. ramesh

    free gift

    ramesh, Sep 2, 2007, in forum: C++
    Replies:
    0
    Views:
    338
    ramesh
    Sep 2, 2007
Loading...

Share This Page