coin toss problem

R

Richard Heathfield

Ian Collins said:
My poorly made point was that C99 is more widely available than some
people make out.

True. It is also /less/ widely available than some people make out.
I still find the "it's new so I won't use it" argument hard to swallow.

Nobody is arguing that as far as I can see. The reason I don't use C99
features is that they're not portable, so using those features makes my
code non-portable. When C99 becomes widespread, that'll be great,
marvellous, and fantastic, and suddenly I'll be able to use VLAs if I want
(not that I see the point) - but in the meantime I'm not holding my breath.
 
K

Keith Thompson

Ian Collins said:
Richard Heathfield wrote: [...]
If you're using a C99 compiler, well, fair enough. If you're using a
compiler adhering to an older standard, like 99.90813774% of us, then your
C compiler is required to issue a diagnostic message for the above code,
which violates this constraint: "The expression that specifies the size of
an array shall be an integral constant expression that has a value greater
than zero." Since limit+1 is not an integral constant expression, a
diagnostic message is required.
Are Solaris users realy that small a minority?

<OT>
Are you saying that Sun's compiler fully supports C99? If so, it's
news to me. What version?
</OT>
 
I

Ian Collins

Richard said:
Ian Collins said:



True. It is also /less/ widely available than some people make out.




Nobody is arguing that as far as I can see. The reason I don't use C99
features is that they're not portable, so using those features makes my
code non-portable. When C99 becomes widespread, that'll be great,
marvellous, and fantastic, and suddenly I'll be able to use VLAs if I want
(not that I see the point) - but in the meantime I'm not holding my breath.
It's a classic chicken and egg situation, users won't use it because it
isn't portable, vendors won't support it because users won't use it!
 
I

Ian Collins

Keith said:
Ian Collins said:
Richard Heathfield wrote:
[...]
If you're using a C99 compiler, well, fair enough. If you're using a
compiler adhering to an older standard, like 99.90813774% of us, then your
C compiler is required to issue a diagnostic message for the above code,
which violates this constraint: "The expression that specifies the size of
an array shall be an integral constant expression that has a value greater
than zero." Since limit+1 is not an integral constant expression, a
diagnostic message is required.

Are Solaris users realy that small a minority?


<OT>
Are you saying that Sun's compiler fully supports C99? If so, it's
news to me. What version?

Studio 11 is getting close. As close as their C++ compiler was to the
C++ standard a few years ago.
 
I

Ian Collins

Keith said:
Ian Collins said:
Keith Thompson wrote:
[...]
It also has declarations following statements within a block. Both of
these features are supported by C99 but not by C90. (They're also
supported by C++, and possibly by some C90 compilers in a
non-conforming mode.)

No, VLAs are not supported by C++ (yet). A constant expression is
required. g++ has them as an (irritating for porters) extension.


See, that's what I get for discussing C++ in comp.lang.c!

(I was probably thinking of the fact that C++ has a looser definition
of constant expressions than C has; some things that would be VLAs in
C are ordinary constant-size arrays in C++.)
Yes, that's correct. Another thing I find strange in C: why isn't
'const int' a constant expression?
 
C

CBFalconer

Ian said:
.... snip ...

Also gcc has supported variable length arrays as an extension for
many years. I've suffered the pain of porting from gcc more than
once.

gcc, without suitable parameters, is NOT a C compiler. The minimum
recommended options for using it for portable coding are:

gcc -W -Wall -ansi -pedantic

which will convert it into a first class C90 compiler. You can
replace -ansi with -std=C99 to have a fairly good C99 compiler. I
add -O1 -Wwrite-strings -Wfloat-equal.

Note that non-portable code is NOT discussed here.
 
B

Ben C

Keith said:
Ian Collins said:
Keith Thompson wrote:
[...]

It also has declarations following statements within a block. Both of
these features are supported by C99 but not by C90. (They're also
supported by C++, and possibly by some C90 compilers in a
non-conforming mode.)


No, VLAs are not supported by C++ (yet). A constant expression is
required. g++ has them as an (irritating for porters) extension.


See, that's what I get for discussing C++ in comp.lang.c!

(I was probably thinking of the fact that C++ has a looser definition
of constant expressions than C has; some things that would be VLAs in
C are ordinary constant-size arrays in C++.)
Yes, that's correct. Another thing I find strange in C: why isn't
'const int' a constant expression?

Well, there is a difference: A "constant expression" must be known at
compile-time, a const int can be initialized with an expression that
isn't evaluated until runtime, you just can't (or shouldn't) then change
the value. I may be wrong (and hope to be corrected if I am), but I
don't think "casting away const" causes any undefined behaviour.

In C++ you've got some special rules that mean "const int a = 2;" can
safely go in a header-file (i.e. you can include it in a lot of source
files and not end up with "duplicate symbol" errors), and works pretty
much just like "#define a (2)". But in "const int b = f();", "const int"
has a meaning much closer to what it always means in C.

I find this strange in C++.
 
K

Keith Thompson

Ian Collins said:
Keith said:
Ian Collins said:
Keith Thompson wrote:
[...]

It also has declarations following statements within a block. Both of
these features are supported by C99 but not by C90. (They're also
supported by C++, and possibly by some C90 compilers in a
non-conforming mode.)


No, VLAs are not supported by C++ (yet). A constant expression is
required. g++ has them as an (irritating for porters) extension.


See, that's what I get for discussing C++ in comp.lang.c!

(I was probably thinking of the fact that C++ has a looser definition
of constant expressions than C has; some things that would be VLAs in
C are ordinary constant-size arrays in C++.)
Yes, that's correct. Another thing I find strange in C: why isn't
'const int' a constant expression?

Because "const" doesn't really mean "constant" (at least not in the
sense used in the phrase "constant expression"); it means "read-only".

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

int main(void)
{
srand(time(NULL));
const int r = rand();
printf("r = %d\n", r);
return 0;
}

Yes, the similarity between the word "constant" and the keyword
"const" is an unforunate source of confusion.
 
I

Ian Collins

Ben said:
Well, there is a difference: A "constant expression" must be known at
compile-time, a const int can be initialized with an expression that
isn't evaluated until runtime, you just can't (or shouldn't) then change
the value. I may be wrong (and hope to be corrected if I am), but I
don't think "casting away const" causes any undefined behaviour.
const int a = 2;
*(int*)(&a) = 3;

would cause UB.
In C++ you've got some special rules that mean "const int a = 2;" can
safely go in a header-file (i.e. you can include it in a lot of source
files and not end up with "duplicate symbol" errors), and works pretty
much just like "#define a (2)". But in "const int b = f();", "const int"
has a meaning much closer to what it always means in C.

I find this strange in C++.

Touché!

"const int a = 2;" is a compile time constant, where as "const int b =
f();" isn't.

I guess the clarity of the distinction depends on one's view of the world.
 
I

Ian Collins

CBFalconer said:
Ian Collins wrote:

.... snip ...



gcc, without suitable parameters, is NOT a C compiler. The minimum
recommended options for using it for portable coding are:

gcc -W -Wall -ansi -pedantic

which will convert it into a first class C90 compiler. You can
replace -ansi with -std=C99 to have a fairly good C99 compiler. I
add -O1 -Wwrite-strings -Wfloat-equal.

Note that non-portable code is NOT discussed here.
Yawn...

But C99 is and the above mentioned gcc extension has been incorporated
into the standard.
 
B

Ben Pfaff

Richard Heathfield said:
[...] your C compiler is required to issue a diagnostic message
for the above code, which violates this constraint: "The
expression that specifies the size of an array shall be an
integral constant expression that has a value greater than
zero." Since limit+1 is not an integral constant expression, a
diagnostic message is required.

I am not sure it is required, because of the following dictum in
the standard (in C99 it's 6.6p10; I seem to recall seeing the
same sentence in C90):

An implementation may accept other forms of constant
expressions.
 
R

Richard Heathfield

Ben Pfaff said:
Richard Heathfield said:
[...] your C compiler is required to issue a diagnostic message
for the above code, which violates this constraint: "The
expression that specifies the size of an array shall be an
integral constant expression that has a value greater than
zero." Since limit+1 is not an integral constant expression, a
diagnostic message is required.

I am not sure it is required, because of the following dictum in
the standard (in C99 it's 6.6p10; I seem to recall seeing the
same sentence in C90):

An implementation may accept other forms of constant
expressions.

I can't find that phrase in my C89 draft. A final trumps a draft, of course,
but I think my draft is quite close to the final. Do you have an exact cite
from C90?

Just to be clear that I have no quibble about its being legal C99, because
C99 does support VLAs. This is purely a C89/90/95/callitwhatyouwill issue.
 
R

Richard Heathfield

Ian Collins said:
Yawn...

But C99 is and the above mentioned gcc extension has been incorporated
into the standard.

No, gcc's VLAs have not been incorporated into the Standard. The semantics
of gcc VLAs differs from that of C99 VLAs, according to gcc's own
documentation.
 
P

pete

Richard said:
Ben Pfaff said:

I can't find that phrase in my C89 draft. A final trumps a draft,
of course, but I think my draft is quite close to the final.
Do you have an exact cite from C90?

ISO/IEC 9899: 1990

6.4 Constant expressions

Semantics

An implementation may accept other forms of constant expressions.
 
I

Ian Collins

Richard said:
Ian Collins said:


No, gcc's VLAs have not been incorporated into the Standard. The semantics
of gcc VLAs differs from that of C99 VLAs, according to gcc's own
documentation.
My lesson for the day, I'd better go and look it up!

Cheers,
 
R

Richard Heathfield

pete said:
ISO/IEC 9899: 1990

6.4 Constant expressions

Semantics

An implementation may accept other forms of constant expressions.

Fair enough. The obvious implication is that a developer may get a clean
compile on one implementation, and yet get a show-stopping constraint
violation on another.

So, if your goal is portable code, steer clear.
 
C

Charles Richmond

CBFalconer said:
I've written this coin toss program, and can't figure out why it isn't
giving accurate results...
cheers,
Ben

#include <stdlib.h>
#include <stdio.h>
#define H 1
#define T 0
#define SENTINEL -1

int count=0, seed=3645, limit=200, in_a_row=6, iterations=100;

void one_run(int seed_passed)
{
int i, x, row_h;
row_h = 0;

seed=(1+seed_passed);
srand(seed);

char A[limit+1];

This code should not compile unless you have a C99 system, which I
doubt. limit+1 is not a constant, so the compiler has no idea what
to do. In addition, you are defining storage after executable
code. Turn up your warning levels. Also you are allowed to use
blanks in expressions, the blank embargo was lifted some years ago.
....and you can take that to the blank. I laughed all the way...
 
B

Ben

Hi,
I don't know what your problem is but I will make some observations anyway.

My initial problem was that I had read in a maths book that the average
no. of 6 heads in a row in a sequence of 200 tosses was at least one...
my program kept providing 0.77
I have since realised that they must have meant "at least 6"...
First of all, get rid of the global variables. There is no need to resort
to global variables in a program this small and simple.

I only started learning programming a few months ago- so I'm not sure
what the problem is with global variables? (And what's an alternative?)
Is there any reason not to use enum instead of the #defines? They are more
appropriate and would probably do what you want.

The #defines seem to do what I want - enums might be more appropriate,
but I haven't yet learnt what they are :)
Don't use the sentinel. Sentinels are something you resort to when there is
a good reason. There is no good reason here.

The sentinel seemed easy enough to use - what potential problems are
there with using them? Why are they only a last resort?
Reduce the program to its essence. You seem to be able to handle command
line, a default set of data, or user supplied data. This is just
obfuscating things right now. Choose one. I would use built in data for
initial testing.

The command line data is just for the seed, so I can manually assess
the degree of probability accuracy ... the default data is probably
unnecessary.
Pay attention to the definition of in_a_row. Does it mean *exactly* n in a
row? The code says no. To determine that your code would have to look at
the next character - the one that breaks the sequence- , and it doesn't do
that. To me, exactly is the most sensible thing to compute. For example,
if in_a_row is 3 what does the following sequence of heads get counted as:
001111111100 ?

It does compute 'exactly x in a row' ... which is what I intended...
(it looks at the character that breaks the sequence when 'i' is
incremented - which breaks the while loop)

while(A==H)
{
i++;
row_h++;
}

if(row_h==in_a_row)
count++;

row_h=0;
I tried the corner cases, in a row = 1 and in a row = 0 and got strange
results.
You might refuse to accept such questions as n = 1 in the final version of
your code.

I'd like to be able to test for n=1 ... so I'll keep trying :)
If n=0, I could just assign the number of tosses to n, and test for
that instead.
Too complicated.

Note that if the number drawn is less than 1/2 RAND_MAX, you have divided
the distribution into two almost equal parts.

My uni textbook says "If you need your program to be portable, and
require the values to be uncorelated even when compiled with the
original rand and srand functions, you should extract the desired value
from high-order bits rather than low-order ones..."
What are those parens for? Just a kind of idle question.

I'm a newbie ... by habbit I tend to stick in as many extra parens as
possible ;)
(I realise now they are reduntant).
 
A

Andrew Poelstra

Hi,


My initial problem was that I had read in a maths book that the average
no. of 6 heads in a row in a sequence of 200 tosses was at least one...
my program kept providing 0.77
I have since realised that they must have meant "at least 6"...


I only started learning programming a few months ago- so I'm not sure
what the problem is with global variables? (And what's an alternative?)
Globals are very difficult to maintain; it is impossible to tell what
functions modify the variables, and where. Much better to pass each variable
to each function.
The #defines seem to do what I want - enums might be more appropriate,
but I haven't yet learnt what they are :)
enums are lists of variables:

enum MyList { itemOne, itemTwo, itemThree };

results in itemOne being 0, itemTwo being 1, and itemThree being 2. You can
also add in definitions:

enum MyList { itemOne, itemTwo = 9, itemThree };

will set itemTwo to 9.
The sentinel seemed easy enough to use - what potential problems are
there with using them? Why are they only a last resort?
Sentinel values are difficult to read and maintain; there are far more elgant
solutions to most problems.
The command line data is just for the seed, so I can manually assess
the degree of probability accuracy ... the default data is probably
unnecessary.
Ensure that your program will work with default values /first/, and then add
functionality for command lines. There's a reason that people are paid large
sums of money for programming: it isn't a one-step easy-to-do process.
Pay attention to the definition of in_a_row. Does it mean *exactly* n in a
row? The code says no. To determine that your code would have to look at
the next character - the one that breaks the sequence- , and it doesn't do
that. To me, exactly is the most sensible thing to compute. For example,
if in_a_row is 3 what does the following sequence of heads get counted as:
001111111100 ?

It does compute 'exactly x in a row' ... which is what I intended...
(it looks at the character that breaks the sequence when 'i' is
incremented - which breaks the while loop)

while(A==H)
{
i++;
row_h++;
}

if(row_h==in_a_row)
count++;

row_h=0;

Don't use tabs on Usenet; use either 2 or 4 spaces for indentation. I've
heard of people using 3 spaces as well. Anything higher or lower is difficult
to read.
I'd like to be able to test for n=1 ... so I'll keep trying :)
If n=0, I could just assign the number of tosses to n, and test for
that instead.

if (n == 1)
{
/* Do stuff here */
}

Tests aren't hard in programming languages.
My uni textbook says "If you need your program to be portable, and
require the values to be uncorelated even when compiled with the
original rand and srand functions, you should extract the desired value
from high-order bits rather than low-order ones..."
I can't imagine how you would make a program "portable" in that you will always
get reasonably random values. If I was in a malicious mood, I could develop a
system where rand() would always return an integer between 0.9 and 1.1.
I'm a newbie ... by habbit I tend to stick in as many extra parens as
possible ;)
(I realise now they are reduntant).
"habit" is how it is spelled. In general, you should avoid unnecessary
parentheses except in long or esoteric expressions.

Ex. x = (y << 3) + b;
x = (a + b) + (c - b) * (r + a) / ((t == y) ? m : n);

I hope that you never type that second one. :)
 
K

Keith Thompson

Andrew Poelstra said:
enums are lists of variables:

enum MyList { itemOne, itemTwo, itemThree };

results in itemOne being 0, itemTwo being 1, and itemThree being 2. You can
also add in definitions:

Quibble: constants, not variables.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,184
Messages
2,570,973
Members
47,529
Latest member
JaclynShum

Latest Threads

Top