I was working on an assignment and decided on checking this following problem with my POD. The assignment basically requires a generation of a multiplication problem and loop forever depending on if he gets it right or wrong. So to generate my problem:
int Elementary::setProblem()
{
srand ( time(NULL));
firstfactor = rand() %1;
secondfactor = rand() %1;
answer = factor1 * factor2;
return answer;
}
However, I was told that this method was the proper way of doing:
void Elementary::setProblem()
{
srand ( time(NULL) );
firstfactor = rand()%10;
secondfactor = rand()%10;
answer = firstfactor * secondfactor;
}
She basically told me that answer = is already sets the private member and that return had no use.
Wouldn't my method be faster since I don't have to set the problem and then make a second function to get the problem?
A setter function, typically, does not return anything.
The whole point of pairs of setter and getter functions is that you call one to set something, another to get the value back. That way, you could, for example, completely avoid storing answer, and just calculating it in the getter when you actually need it - in this particular case, this probably gives no benefit, but in some cases, that may be a benefit.
Related
I have seen code like,
Approach 1
for(int i = 0; i < 200; ++i) {
do_some_stuff(i);
}
Approach 2
const int max_limit = 200;
for(int i = 0; i < max_limit; ++i) {
do_some_stuff(i);
}
Is there any advantage for Approach 2 over Approach 1?
It's generally good practice to replace an integer constant by something with a meaningful name, so I'd say that's the main advantage of the second one. However, if the code is really simple than the extra line may just make it one more line to parse.
That said, if you are replacing something like this:
for(int i = 0; i < something.size(); ++i) {
do_some_stuff(i);
}
with
const int something_sz = something.size();
for(int i = 0; i < something_sz; ++i) {
do_some_stuff(i);
}
then there is the added benefit that it makes it obvious to the reader, as well as the compiler, that something.size() isn't changed by the call to do_some_stuff(i).
Use of magic numbers, such as 200 in your example, anywhere in your code is cause for concern. It makes the code harder to understand and maintain.
Approach 2 is better if the variable is appropriately named. max_limit has no more meaning than 200. However, if you use max_number_of_books, it is a lot more meaningful than 200.
For me, approach 2 is better, when you define a const like const int max_num_of_students it looks more meaningful and someone reading to that code, can easily understand what is going on.
Another advantage of using such const in loops is that if you are printing names of students more than one time, you don't need to change the condition in your loop every time the count of students gets increased. Go to your variable and change it to new student count.
We should avoid to using the magic number anytime when wrote codes. Because if you use the number 200 only, maybe others cannot understand your codes' intention well. But when you use const int max_limit = 200;, we can understand the number 200's meanings. Especially when your codes was very complex, you must write it with the second way.
2nd Approach is better as by this you can also get the value from the user:
cin>>max_limit;
Approach 2 is better as per my opinion.
Readability is enhanced.
For example:
int currentPortNo=getPortNo();
const int inputPort=80;
if(currentPortNo == inputPort){
//Get input from port
}
when compared to:
int currentPortNo=getPortNo();
if(currentPortNo == 80){
//Get input from port
}
Maintainability is enhanced since if we want inputPort should be initialized(changed) with 81 instead of 80 due to new requirements/limitations we can simply use:
const int inputPort=81;
instead of changing all the occasion wherever the value 80 is used in entire program.
Also, if you need to pass a pointer around the program.
Can have the scoping and typing properties
I would like to know the difference between functions that return a value and functions that set a value to a pointer, for example:
Pointer:
int myVal;
ptr_multiply(5, 5, &myVal);
cout << myVal << endl; //Output: 25
Return:
int myVal = rtn_multiply(5, 5);
cout << myVal << endl; //Output: 25
My question focuses in what method to choose when creating functions and why, as well as what advantages/disadvantages can we find in each of them.
Readability is the main reason functions typically return what you expect them to return. However, as this is highly subjective, I suggest you strive for consistency within your project.
When you want a function to return multiple things and not group them all together in a structure just so you can return them, an alternative is to return them in output parameters.
If you have big pieces of data to return, then you might come across to performance-bottlenceks. The reason is that that the returning value must be copied.
But in the most cases you don't have to worry about that, because modern compilers are capable of auto-inline things like that.
Side note: In C++ try to avoid naked pointers as much as possible (use references, smart-pointers)
One advantage to use the "pointer" method is that you can have multiple "return" values by passing in non-const references or pointers. For example:
int output1;
int output2;
get_values("input", &output1, &output2)
You can return a success/failure:
int v = -1;
if(ToInt("wibble",&v)){
// do something with v
}
Would fail as "wibble" can't be converted to an int.
The other useful thing is that the function doesn't have to change v:
int v = previousValue;
UpdateIfNewValueFound( &v )
Return the value. With modern compilers there should be almost no difference in performance between the two, but returning the value has several advantages:
By definition, it's what a function should do (i.e. a function maps from a domain to a codomain).
It's self-documenting; if I'm using an unfamiliar API, unless there is good documentation, it can get confusing what is input/output if values are returned in the parameter set. With a returned value there is no ambiguity, and requires less documenting.
It's easier to use - can half the number of lines needed! Compare
int r = f();
to
int r;
f(&r);
It could make you a better programmer; you have to put more effort into returning multiple values from a function (e.g. via a struct or pair, as opposed to adding another parameter). If you find you need to do this often, the additional effort may force you to think more carefully about your code design - it's usually better for a function to just do/return one thing.
Another difference is stack or heap.
A return-value lies on top of the stack. The pointer-variant lies in heap.
For instance (sensless recursive code to demonstrate return on stack):
typedef std::array<int,1000> KByte;
KByte tmp;
KByte f(int nr) {
if (nr == 1) { tmp[nr]=nr; return tmp; }
else { tmp[nr]=nr; return f(nr-1); };
}
void f2(int nr, KByte& ret) {
if (nr == 1) { ret[1]=1; }
else { ret[nr]=nr; f2( nr-1, ret ); }
};
Calling
KByte t = f(999); /* Stack error */
shoud give you an stack-size error, since 1000 KByte (1GB) on the stack is to much.
Calling
KByte t2;
f2( 999, t2 );
should work without stack problem. (It also uses recursion depth 1000, but does not lie the return value on the stack.
I'm thinking about a different implementation of this part of a code:
unsigned int whyamIexisting=100000; // also good for me static unsigned ...
double rand_number_generation(){
// create random number [0,1]
static unsigned int rand_counter=0;
rand_counter++;
if( rand_counter > whyamIexisting) {
update_my_seed(time(NULL));
rand_counter=0;
}
// random number generation
return thats_your_gorgeous_numb(); // random algorithm
}
main(){
...modify whyamIexising
...use rand_number_generation() several times
...
}
Should I not use global variable? And if yes what solution will you suggest?
thanks!
If you are working with multiple functions and using a global variable, i would suggest you not to modify it and instead use local variable for storing it and then do the modification.
I usually avoid using global variables. :-)
There... gone!
double rand_number_generation(unsigned int whyamIexisting){
// create random number [0,1]
static unsigned int rand_counter=0;
rand_counter++;
if( rand_counter > whyamIexisting) {
update_my_seed(time(NULL));
rand_counter=0;
}
// random number generation
return thats_your_gorgeous_numb(); // random algorithm
}
main(){
unsigned int limit = 17;
...use rand_number_generation(limit) several times
...
}
There is no point having a global variable in your case. It only makes the program hard to maintain if it were to grow. It doesn't add anything in the example you have given.
I don't know the rest of code, so it's based on fragments you posted and may be completely wrong.
whyamIexisting is kind of a description for environment where rand_number_generation is run, but it also describes it's state, same as rand_counter.
From tags I see that you write in C++, which is an object oriented language. The thing about object orientation is that you have, you know, objects. Probably not everyone will agree with me (thinking about my High School IT teacher), but I personally consider putting everything that has it's own state into class as a good practise. Does object containing whyamIexisting as it's field, rand_counter as another and rand_number_generation as it's method (and probably getter and setter for whyamIexisting) solve your problem?
Unless you don't use whyamIexisting anywhere else in the code, because then you can simply make it local in main and pass as parameter to function rand_number_generation.
This question already has answers here:
What's the Right Way to use the rand() Function in C++?
(5 answers)
Closed 9 years ago.
Whenever I call a specific method in my class file, I return a random value, but it then proceeds to return the same value each time that method is called again.
For example
int CommuterTrain::getRandNumber(int maximumValue)
{
srand(unsigned(time(NULL)));
int maximum = maximumValue;
return rand()%maximum+1;
}
void CommuterTrain::loadRiders()
{
int passengers = getRandNumber(350);
currentRiders += passengers;
if (currentRiders > maxCapacity) {
cout << "The train has reached capacity! \nSome people were left at the station."
<< endl;
currentRiders = maxCapacity;
}
else {
cout<<passengers<<" pax have entered the vessel"<<endl;
}
}
Let's say the generator produces a number of 215 pax. When I call the method again, it doesn't randomize again and I wind up with 215 every time.
Is the issue in the generator, or is it in the following method?
You keep reseeding it. With the same seed (assuming you have a computer that is newer than 1920 and can therefore execute your code in under a second†). Don't do that.
It means you keep regenerating and restarting the same pseudo-random sequence over and over again. Consequently, you keep pulling out the same first value in that sequence with each call to rand().
Seed only once in your program.
You could put the srand call in main, for example.
† It could take around a second provided you began execution just as a new second began. Integer logic and all that. Whatever.
Your problem is, that you're seeding the random engine with every call to your function:
int CommuterTrain::getRandNumber(int maximumValue)
{
srand(unsigned(time(NULL))); // <<< This line causes your problems
int maximum = maximumValue;
return rand()%maximum+1;
}
The current time() result is unlikely to change significantly in between calls to the getRandNumber() function.
You should call srand(time(NULL)) once outside your function instead (e.g. in your CommuterTrain class constructor, or even better from main() only).
Homework, just advise please
Apparently my idea of what returning something in a method does is wrong. I'm trying to write methods for getting derivatives of numbers and operations. So far I just wanted to get the derivative of a non-negative number that isn't accompanied with an "x" (result should be zero no matter what value is given).
The code is pretty long and needs to be cleaned up so I'll just include the method, the call, and what I'm getting.
Method:
int noXDerivative(int tempInt, string tempX)
{
if (tempX == "")
{
tempInt = 0;
}
return tempInt;
}
void getDerivatives(int tempInt, string tempX, int tempInt2, string tempX2, char tempOperator)
{
noXDerivative(tempInt, tempX);
noXDerivative(tempInt2, tempX2);
}
The call:
getDerivatives(tempNumInt, tempNumX, tempNum2Int, tempNum2X, expression[iterator]);
I also called the "noXDerivative" directly to see what would happen but the result didn't change. The test I'm running right now is "5 + 6" (tempNumInt is 5 and tempNum2Int is 6). I keep getting 11 when I need to get 0 (again, there are no "x"s). I was hoping that if I put tempNumInt as one of the parameters it would be changed from 5 to 0 within the noXDerivative method but it doesn't. How do I correct this?
I have to say that I don't understand what it is that you're trying to do.
Nevertheless, to achieve your goal of modifying tempInt inside getDerivatives(), you can either do:
tempInt = noXDerivative(tempInt, tempX);
Or, you can modify the noXDerivative() function to take its argument by reference, rather than by value:
int noXDerivative(int &tempInt, string tempX)
{
...
}
return does just that--it returns a value. It doesn't change the value passed in. If I understand your code correctly, I bet that if you had something like
int result1 = noXDerivative(tempInt, tempX)
result1 would hold the value 0. Mind you, tempInt and tempInt2 in getDerivatives won't be modified then, so you'll need to figure that out...
well, not a lot to "advise". The problem here is that when a routine returns a value, the call must be used as a left hand value.
tempInt = noXDerivative(tempInt, tempX);
You will not modify the value of tempInt otherwise, at least with the current signature of your routine. You are passing tempInt as an argument by value with that call, and any modifications you perform to tempInt will occur on the local stack frame of that routine.