patterncppMajor
C++ Coin flip simulator and data collector
Viewed 0 times
coincollectorflipandsimulatordata
Problem
Asks the user for the chance of a coin landing on heads, the number of trials per experiment, and the number of experiments. For example, given 5 trials per experiment and 20 experiments, the program will flip a coin 5 times and record the results 20 times. Then, it displays the results, as well as the theoretical and observed probabilities of each event happening.
I turned this in already but I really enjoyed doing the assignment and I'd like to know how to make it better, faster, etc. I'm pretty new to computer science so I'd like to learn the correct practices and everything. Right off the bat I know that I should pass things by reference instead of by value and that I shouldn't have used global variables.
```
//Name Lastname
//Class
//Coin Flip Simulation
//LIBRARIES
#include
#include
#include
#include
#include
using namespace std;
//FUNCTION PROTOTYPES
bool generate(); //Performs a coin flip with the given chance
void runExperiment(); //Performs and prints the results of the trials
void getInfo(); //Gets the information to perform the experiment
int choose(int, int); //Performs a combination (nCk)
double probability(int); //Calculates the probability of a coin hitting heads n times (binomial thrm)
//GLOBAL VARIABLES
double chance = 0.5; //Chance of landing on heads
int numTrials = 5; //Number of trials per experiment
int numExperiments = 1000; //Number of experiments
bool printT = false; //Whether to print the results of each trial
int main()
{
srand(time(NULL));
getInfo();
runExperiment();
getchar();
getchar();
return 0;
}
void getInfo()
{
cout > chance;
cout > numTrials;
cout > numExperiments;
cout > printT;
}
void runExperiment()
{
int m = 0, n = 0, a[22];
for (int b = 0; b n)
return 0;
int r = 1;
for (int d = 1; d <= k; ++d)
{
r *=
I turned this in already but I really enjoyed doing the assignment and I'd like to know how to make it better, faster, etc. I'm pretty new to computer science so I'd like to learn the correct practices and everything. Right off the bat I know that I should pass things by reference instead of by value and that I shouldn't have used global variables.
```
//Name Lastname
//Class
//Coin Flip Simulation
//LIBRARIES
#include
#include
#include
#include
#include
using namespace std;
//FUNCTION PROTOTYPES
bool generate(); //Performs a coin flip with the given chance
void runExperiment(); //Performs and prints the results of the trials
void getInfo(); //Gets the information to perform the experiment
int choose(int, int); //Performs a combination (nCk)
double probability(int); //Calculates the probability of a coin hitting heads n times (binomial thrm)
//GLOBAL VARIABLES
double chance = 0.5; //Chance of landing on heads
int numTrials = 5; //Number of trials per experiment
int numExperiments = 1000; //Number of experiments
bool printT = false; //Whether to print the results of each trial
int main()
{
srand(time(NULL));
getInfo();
runExperiment();
getchar();
getchar();
return 0;
}
void getInfo()
{
cout > chance;
cout > numTrials;
cout > numExperiments;
cout > printT;
}
void runExperiment()
{
int m = 0, n = 0, a[22];
for (int b = 0; b n)
return 0;
int r = 1;
for (int d = 1; d <= k; ++d)
{
r *=
Solution
There's a lot that can be improved here, so I hope that these suggestions are useful to you.
Don't abuse
Putting
Make sure you have all required
The code uses
Use only required
The inverse of the above suggestion is to avoid having extra
So I advocate omitting it; others disagree (often vehemently!) In any case, if you encounter code that omits it, you'll know that it's explicitly supported by the standard and you'll know what it means.
Don't abuse
using namespace stdPutting
using namespace std at the top of every program is a bad habit that you'd do well to avoid. Make sure you have all required
#includesThe code uses
rand() but doesn't #include . It's important to make sure you have all required include files to make sure your program compiles reliably.Use only required
#includesThe inverse of the above suggestion is to avoid having extra
#includes. In this case ` does not appear to be used. Only include files that are actually needed.
Avoid the use of global variables
As you have already noted, global variables should be avoided in favor of local variables. It's generally better to explicitly pass variables your function will need rather than using the vague implicit linkage of a global variable. For example, the runExperiment function relies on numExperiment and numTrials, so those should be passed parameters.
Use better naming
The variables numTrials and numExperiments are good names because they hint at the significance of those variables to this program. However, the variables in runExperiment are named m, n, a, b, etc. which are not at all descriptive. Similarly runExperiment is a decent function name but generate and getInfo are not (generate what?; get what info?).
Use a better random number generator
The way you're using rand() could be greatly improved. Instead of your existing code for generate, you could use this:
bool generate() {
return rand() < chance*RAND_MAX;
}
The advantage is that it does not skew the results as mentioned in a comment. Better still, use std::bernoulli_distribution which uses the modern C++ random number generation capabilities.
Use objects
The current code is largely just plain procedural C rather than C++. I would recommend wrapping all of the global variables into an object, say CoinToss and then making most of the functions member functions of that object.
Don't use std::endl when '\n' will do
Using std::endl emits a \n and flushes the stream. Unless you really need the stream flushed, you can improve the performance of the code by simply emitting '\n' instead of using the potentially more computationally costly std::endl.
Sanitize user input better
If I enter a string such as "Edward" or a negative number into the program, bad things happen. Users can do funny things and you want your program to be robust. One way to do that is to read in a std::string and then parse it, looking for errors.
Omit return 0
When a C or C++ program reaches the end of main the compiler will automatically generate code to return 0, so there is no need to put return 0; explicitly at the end of main.
Note: when I make this suggestion, it's almost invariably followed by one of two kinds of comments: "I didn't know that." or "That's bad advice!" My rationale is that it's safe and useful to rely on compiler behavior explicitly supported by the standard. For C, since C99; see ISO/IEC 9899:1999 section 5.1.2.2.3:
[...] a return from the initial call to the main function is equivalent to calling the exit function with the value returned by the main function as its argument; reaching the } that terminates the main function returns a value of 0.
For C++, since the first standard in 1998; see ISO/IEC 14882:1998 section 3.6.1:
If control reaches the end of main without encountering a return statement, the effect is that of executing return 0;
All versions of both standards since then (C99 and C++98) have maintained the same idea. We rely on automatically generated member functions in C++, and few people write explicit return; statements at the end of a void` function. Reasons against omitting seem to boil down to "it looks weird". If, like me, you're curious about the rationale for the change to the C standard read this question. Also note that in the early 1990s this was considered "sloppy practice" because it was undefined behavior (although widely supported) at the time. So I advocate omitting it; others disagree (often vehemently!) In any case, if you encounter code that omits it, you'll know that it's explicitly supported by the standard and you'll know what it means.
Code Snippets
bool generate() {
return rand() < chance*RAND_MAX;
}Context
StackExchange Code Review Q#161041, answer score: 28
Revisions (0)
No revisions yet.