For clarification, let's consider the following program:
#include <iostream>
int main(void) {
short int i; // declaration
short int value;
short int sum;
i = value = sum = 0; // initialization
std::cout << "Enter a value: ";
std::cin >> value;
while (i != value) { // ### here's the confusion ###
sum += i;
i++;
}
std::cout << "Total sum: " << sum << std::endl;
return 0;
}
Look at the while (i != value), when this expression is given, the results shows Total sum: 45 whereas if we put while (i <= value), it shows Total sum: 55. (Input's given 10 for example)
Here, the confusion is, when should we use != and <= or >= operations in loops, any specific condition?
According to TutorialsPoint's Operators Reference
it tells that != (returns true used when two operands are unequal).
<= (returns true when used when we need to ensure if the first operand is lesser than or equal to second).
It was expected to get no difference in output, but something's misunderstood.
This while loop
while (i != value)
does not include the iteration when i is equal to value because in this case the condition i != value evaluates to false.
This while loop
while (i <= value)
includes the iteration when i is equal to value because in this case the condition i <= value evaluates to true.
In fact the first condition can be rewritten the following way (provided that initially i is less than value)
while ( i < value )
Now compare it with the condition in the second loop that in turn can be rewritten like
while ( i < value || i == value )
That is you have two different conditions.
With
while( i <= value)
the last iteration is with i == value. With
while ( i != value)
The body of the loop will not be executed when i == value. That is the reason you observe the difference.
This is a good chance to learn how to use a debugger. And/Or realize that your example is already too complicated to directly see what is going on. You would have spotted the difference more easily with
int i = 0;
int value = 5;
while ( i != value) {
std::cout << i << " ";
}
i = 0;
while ( i <= value) {
std::cout << i << " ";
}
Related
I'm supposed to write a small code that generates a random number between 2 and 100 and then checks if its a perfect number. I don't get any bugs from the compiler but the output doesn't show my cout lines like " x is a perfect number". Can someone help me with finding the reason?
#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;
bool PerfectCheck(int x) {
int t; // divisor
int sum; // sum of divisors
for (t = 0; t <= x; t++ ) {
if (x%t == 0) {
sum = sum + t;
}
}
if (sum == x)
return true;
else
return false;
}
int main() {
srand(time(NULL));
int x = rand()%(100-2+1)+2;
if (PerfectCheck(x) == true )
cout << x << "is a perfect number.";
else
cout << x << "is not a perfect number.";
return 0;
}
There are three problems in your PerfectCheck function. First, you don't initialize the sum variable, so it can start off with any value whatsoever; you should set it to zero explicitly in the declaration.
Second, your for loop starts with t as zero, and you check x % t. The modulo operator implicitly involves a division, so using a left-hand value of zero has the same issue as trying to divide by zero, which will cause a crash.
Third, when checking for a perfect number, don't use that number itself in the sum; so, stop your loop with t < x instead of t <= x.
Also, as mentioned in the comments, you can simplify the return statement. The code below works, in the tests I have performed:
bool PerfectCheck(int x)
{
int sum = 0; // sum of divisors - MUST BE INITIALIZED (to zero)
for (int t = 1; t < x; t++) { // DO NOT INCLUDE X ITSELF!!
if (x % t == 0) {
sum += t;
}
}
return (sum == x); // This will already give a "true" or "false" bool value.
}
You could actually make the code a tiny bit more 'efficient', by initializing sum to 1 and then starting the loop from t = 2 (all numbers divide by 1, after all).
Feel free to ask for further clarification and/or explanation.
if (x%t == 0) calculates the remainder after dividing x by t and compares the result with 0. That statement is correct, but look at the previous code for (t = 0; t <= x; t++ ) {. The first value of t is 0, so you have a division by zero. More than likely that is crashing your program which is why you see no output. Change for (t = 0; t <= x; t++ ) { to for (t = 1; t <= x; t++ ) {.
Also I believe the definition of a perfect number does not include division by the number itself. So the for loop should actually be for (t = 1; t < x; t++ ) {.
Finally you are using the sum variable to add up the divisors but you do not give it an initial value. Your code should say int sum = 0;.
Three errors in a ten line program (plus various style issues). Imagine how many errors here might be in a 5000 line program. Programming is tricky, you have to be very focused and get your code exactly right, nearly right is not good enough.
C++ Code:
#include<iostream>
using namespace std;
int main()
{
int N;
cin>>N;
int *A = new int[N];
int i=0;
for(i=0;i<N;i++)
cin>>A[i];
while(cout<<A[--N]<<' ' and N);
delete[] A;
return 0;
}
Print the integers of the array in the reverse order in a single line separated by a space.
Does anyone know what is "and N" do in cout statement?
It's a cryptic way of writing:
while( (cout<<A[--N]<<' ') and (N != 0) );
// output is successful and N is not equal to zero.
It could be written more clearly as:
for ( ; N != 0; --N)
{
cout << A[N-1] << ' ';
}
Since it's theoretically possible for N to be negative, it will be better to use:
for ( ; N > 0; --N)
{
cout << A[N-1] << ' ';
}
N is an integer variable, value of type int can be implicitly converted to bool (non zero becomes true and zero becomes false). So the expression basically sais execute when result of operator<< converted to bool is true and N is not equal to zero. Logically this code
while(cout<<A[--N]<<' ' and N);
is equal to:
do {
bool b1 = cout<<A[--N]<<' ';
bool b2 = N;
} while( b1 and b2 );
actual code is a little different due to short circuit but that differences are unimportant in this case.
The part and N that can be also written like && N of the while statement
while(cout<<A[--N]<<' ' and N);
that as it has been pointed out can be rewritten like
while(cout<<A[--N]<<' ' && N != 0);
checks that N that is being decreased (A[--N]) in each iteration of the loop is not equal to 0.
So the loop outputs elements okf the array in the reverse order.
The word and is a so-called alternative token for the primary token &&.
It is just a way of writing the code by some programmers.
It is actually written as
while( (cout<<A[--N]<<' ') and (N != 0) );
Basically 'and' operator returns true when both operands are non zero values.
So cout will give number of characters it printed which will be non zero in this case and until the value of N becomes zero your loop will be execute.
I expect "match!" when the n2 tail is the same that the n1 tail, otherwise, "do not match!".
Example of "match!": n1 = 123456 and n2 = 3456.
The problem is when I enter, for example, n1 = "45" and n2 = "645". It should not match, but the output is "match!".
bool different_tail = false;
char n1[11], n2[11];
cin >> n1 >> n2;
for(int i = strlen(n1)-strlen(n2); i < strlen(n1); i++){
if(i < 0 || n1[i] != n2[i-(strlen(n1)-strlen(n2))]){
different_tail = true;
break;
}
}
if(different_tail)
cout << "does not match!" << endl;
else
cout << "match!" << endl;
I don't want to use other ways to solve the problem (like, strcmp, etc...), I want to understand what's happening.
What happens is that with n1 being 45 and n2 being 645, the loop variable i will start at -1, i.e. it is negative.
However, strlen yields an unsigned value (a value of type size_t). When comparing a signed with an unsigned value (as you do in the expression i < strlen(n1)), the signed value is converted to an unsigned value. Since it's negative, this causes an underflow, so i is a very large value -- larger than strlen(n1).
You can observe the same effect with e.g.
int i = -1;
size_t x = 5;
if (i < x) {
cout << "yes\n";
} else {
cout << "no\n";
}
This program prints no.
You can avoid your issue by casting the return value of strlen, i.e. change your loop condition to
i < static_cast<int>(strlen(n1))
This question (and the accompanying answers) provide a more in-depth discussion of this topic.
Look at this line:
for(int i = strlen(n1)-strlen(n2); i < strlen(n1); i++){
here i is an int whereas strlen(n1) is an size_t(an unsigned integer type). Performing "less than" operator between signed and unsigned type will convert all operands to unsigned types, in this case unsigned(i) becomes a very large integer, so the for loop is never executed.
BTW, it's not a good practice to use strlen in for loop, since strlen is an expensive function and will be called at every iteration. You can store strlen result in an variable and use the variable instead.
I know for a fact that the if statement if ( (roll == i) && (result == true) ) is true many times during the 2500 iterations but when I output winRolls[1] or any other index of winRolls after the higher level for loop completes its 2500 iterations, the value of winRolls[1] and every other index always has a maximum value of 1. Does this have something to do with a characteristic of c++ arrays or am I missing something else?
int winRolls[10]
for (int i = 0; i < 2500; i++)
{
for (int j = 1; j < 10; j++)
if ( (roll == j) && (result == true) )
{
winRolls[roll] = winRolls[roll] + 1;
}
}
cout << winRolls[1] << endl;
cout << winRolls[2] << endl;
cout << winRolls[3] << endl;
Your code has few problems.
winRolls size is [10] and you are accessing it based on i (instead of j, which has correct limit for winRolls). If roll == i is true for say 1000 then you are accessing out of array range. Which will not help you getting desired output as well as you enter an undefined behavior.
Where are you initializing winRolls? If you do not initialize but increment its contents anyway, you might end up with garbage values (values that are different in each run of the program). Also, how will roll == i be true many times during the 25000 iterations? Unless you are updating the value of roll (which I do not see in the code), this inner loop will execute either only once or maybe never depending on what value roll has.
Try cout << winRolls[roll] << endl; at the end.
You're incrementing the value in winRolls[roll] every time.
It looks like the code here is right. Your problem may lie elsewhere in your code.
I'm doing the first project euler problem and I just did this
#include <iostream>
using namespace std;
int main(){
int threes =0;
int fives = 0;
int both = 0;
for (int i = 0; i < 10; i++){
if(i%3==0){
threes += i;
}
if(i%5==0){
fives += i;
}
if ( i % 5 == 0 && i % 3 == 0){
both += i;
}
}
cout << "threes = " << threes << endl;
cout << "fives = " << fives << endl;
cout << "both = " << both << endl;
cout << " threes + fives - both = " << endl;
int result = (threes + fives) - both;
cout << result<< endl;
return 0;
}
My professor recently corrected me for doing this in a different problem saying something about else statements,
but I don't understand WHY i have to add else in front of the next if. for what its worth I have another version with else if(i%5){ fives += .... }
and they both work and get me the right answer.
My question is whats inherently wrong with this way of thinking, is it stylistic or am I not thinking logically about something?
If it works, why use switch statements ever?
The only thing that I see wrong with your implementation is that in the case where the number is both a multiple of 3 and a multiple of 5 not only is the both variable incremented but the fives and threes variables are also incremented. Based on what the professor described I believe he wants you to use an else-if so that the both variable is the only one that is incremented when you pass in a number that is both a multiple of 3 and a multiple of 5.
The reason you get the correct answer both ways is because you are only going to 10 in the for loop, if you increase it to i <= 15 you will get fives and threes being 1 higher than I think he intended.
For example:
for( int i = 0; i < 10; i++ )
{
if( ( ( i % 3 ) == 0 ) && ( ( i % 5 ) == 0 ) )
{
both++;
}
else if( ( i % 3 ) == 0 )
{
threes++;
}
else if( ( i % 5 ) == 0 )
{
fives++;
}
}
The else branch in an if-else statement is only executed if the if branch is false. If you just have two if statements in a row, they'll both be executed, which can be a waste. In the below code, the else prevents the second computation from running if the first is satisfied.
if (expensive_computation1()) {
...
}
else if (expensive_computation2()) {
...
}
Additionally, it's clearer to humans reading the code whether both if statements should be allowed to run or whether only one should.
In this case, maybe you really want this:
if (i % 5 == 0 && i % 3 == 0) {
both += i;
} else if (i % 3 == 0) {
threes += i;
} else if (i % 5 == 0) {
fives += i;
}
(why you do += i instead of ++ I don't know but you didn't explain, so I just copied it)
In your code, threes and fives were incremented even if it would also increase both, which depending on your problem may not be what you want. If you do the if/else way I've just presented, only one of the three variables is increased.
Why use if-else instead of multiple if's?
if-else & if would achieve the same results but if-else achieves them in a performance enhanced way. with multiple if's every if condition will have to be checked. With if-else only one conditional check will have to be performed and the rest of the conditions just don't need to be checked at all.
This would not affect a small program like the one you have but it will sure have some impact in potentially expensive function being called repeatedly over and over again.
If it works, why use switch statements ever?
With nested if-else conditions the code is hard to read and understand. The switch-case construct helps to represent the conditions in a much easier to read & understand format.
To me it looks like stylistics. You can use some autoreformating tool that follows certain established stylistic look (K&R, ANSI, GNU, etc.)
For example astyle is such tool, http://astyle.sourceforge.net/ - just reformat your code with it, and you might have a happy professor.