Figuring out an expression to evaluate a loop - c++

this is a broad question, with a specific example. My question is, how do you figure out how to evaluate an algorithm or expression in a loop?
In the example beblow, I figured out how to use a loop to calculate a square root using a counter with the babylonian algorithm and it appears to be working ok.
But I can't figure out how evaluate this to a certain degree, say within .01 without using a counter. I see other people on the web doing it without a counter but the abililty to do it eludes me.
Here is my counter version:
int count(20);
while (count > 0 )
{
if (guess <= (guess * p) + guess)
prevGuess = guess;
else
r = input / guess;
guess = (guess + r) / 2.0;
count -= 1;
cout << "\nGuess = " << guess;
}
I've tried doing things like:
while ((guess - lastGuess) / lastGuess)
and
while(guess - lastGuess * .01)
But I either get just one interation or an infinite loop.
What is a good method to figure how to evaluate any algorithm inside a loop?
And I don't mean just for this little program, I mean for anything, even something like x + y = 2.
Would you do something like:
while(x + y !=2) {}
Thanks!

Normally this kind of computation can stop when the next iteration doesn't change the value by much; for example
for(;;) {
double next_v = (v + (n / v)) / 2;
if (fabs(v - next_v) < eps) break; // We got there
v = next_v;
}
where eps is the accuracy you want in the result.

You need to compare your error to your determined error limit, instead of zero as your attempts do.
You would use
while (abs((guess - lastGuess) / lastGuess) > .01)
for a relative error of .01, and
while(abs(guess - lastGuess) > .01)
for an absolute one.

In while (and every loop) there is condition which tells program when to stop it. This conditions must be some expression which return true or false value. Simpler, it's just an equation, or something which gives as clear answer: true or false. In your example expression like : ((guess - lastGuess) / lastGuess) isn't returning either true nor false. It returns some numbers etc.
Expression like ((guess - lastGuess) / lastGuess) == 4 will return true if ((guess - lastGuess) / lastGuess) will be equal to 4 and false if not. This example will work: while(x + y !=2). Program will call loop until x+y is equal 2.

Related

C++ IF Statement inside a function issue

I am having some trouble with a basic program for a C++ class. In the following function, i have debugged and the arguments being passed in are correct, however the if statement below is returning 'F' for the first element of the array I pass in, and the second and each thereafter score I pass in is being returned as 'D'.
When I do the math out, my data set should hit each part of the if statement at least once, however im guessing maybe my PEMDAS is off?
Here is the if statement:
char grade(double score, double m, double s) {
if (score < (m - 1.5 * s)) {
return 'F';
}
if ((m - (1.5*s)) <= score < (m - (0.5 * s))) {
return 'D';
}
if ((m - (0.5 * s)) <= score < (m + (0.5 * s))) {
return 'C';
}
if ((m + (0.5 * s)) <= score < (m + (1.5 * s))) {
return 'B';
}
if ((m + (1.5 * s)) <= score) {
return 'A';
}
else {
return 'X';
}
}
An expression like:
a < b < c
does not do what you think it does. It actually evaluates as:
(a < b) < c
where a < b is a truth value giving 0 for false and 1 for true`. Then that value is used in the rest of the expression.
By way of example, the expression 100 < 200 < 42 will be true because 100 < 200 evaluates to 1, which is definitely less than 42.
Instead you should be using something like:
(a < b) && (b < c)
In any case, you can clean up that code quite a bit by realising that:
The construct if (condition) return else ... is totally unnecessary - the return means that the rest of the code will execute only if condition is false, rendering the else superfluous.
Because your ranges are mutually exclusive, the checks can be simplified. In other words, no need to check if (m - (1.5*s)) <= score in the D case since, if that weren't true, the code would already have returned F.
It is currently impossible to get an X grade since there is no score that doesn't get captured one of the if statements, excepting possibly some edge cases like NaN but I'm going to assume you're not worried about that.
With those points in mind, the code can be simplified to:
char grade(double score, double m, double s) {
if (score < m - 1.5 * s) return 'F';
if (score < m - 0.5 * s) return 'D';
if (score < m + 0.5 * s) return 'C';
if (score < m + 1.5 * s) return 'B';
return 'A';
}
We would need to know the input data values to have a complete understanding, however as others have pointed out, comparisons don't work like that in C++.
Take this comparison:
(m - (1.5*s)) <= score < (m - (0.5 * s))
What this is doing is first evaluating:
(m - (1.5*s)) <= score
Due to the first if statement failing, this will always evaluate to true. In C++, boolean values are integers, and true is usually represented by "1" (in practice it doesn't have to be, and can be represented by any non-zero number, but I think in this specific case it's being set to 1).
Then it's evaluating:
1 < (m - (0.5*s))
Which I'm assuming always returns true given your values of "m" and "s".
What you should be doing instead is using a compound statement:
if (m - 1.5*s <= score && score < m - 0.5*s)
(you can keep the parentheses if you like, but they're unnecessary here due to C++'s operator precedence rules)
Just drop all of the lower-bound comparisons (which, as others have said, do not do what you thought): if any of them don’t apply, you would already have returned one of the lower scores.

Converting if-else to for loop

int max_range = 100;
// I do not want to add more else if.. Actually max range is still 100 with more else ifs.
// Range can take values from 0 to 100
if (range <= 10){
a[0]= value;
}
else if (range > 10 && range <= 20){
a[1]= value;
}
else if (range> 20 && range <= 30){
a[2]= value;
}
else if (range > 30 && range <= 40){
a[3]= value;
}
else if (range> 40 && <= max_range){
a[4]= value;
}
It is simple code. I would like it to remove the nested else if's and use a for loop.
How can I convert this into a for loop?
You don't need a loop, you are doing one action.
a[std::max(0, std::min(4, (range - 1) / 10))] = value;
My other answer is very particular to the boundaries being multiples of 10. A runtime modifiable version would be something like
std::set<int> boundaries = { 10, 20, 30, 40, max_range };
// ... potentially modify `a` and `boundaries`, keeping the number of elements equal
a[std::distance(boundaries.begin(), boundaries.lower_bound(range))] = value
I would like it to remove the nested else if's and use a for loop Probably incorrect expression: There's no nested if-else in your example.
Loops, if-else and switch work differently however they all handle conditions:
Loops do iteration; Checking for some condition n times whereas if, switch they check once. So you cannot convert a if-else into a loop.
It's really a good programming trying to make the code effective and as smaller as possible but it is not always the case. If so why such experts build a huge programs with maybe millions of code lines.
Your code works fine.

How to deal with overlapping values in c++?

I'm currently trying to solve a programming problem that involves different ranges of values that overlap. The task is to accept input, in E-notation, and that is where the overlap of range inevitably occurs.
I have 2 ranges that overlap at 1E-11. 1E-11 and lower and 1E-11 and higher
The output would be 1E-11 is either x or it is y. Programmatically i would solve it like this:
(X_MIN would be 1E-11 and X_MAX 1E-8)
(Y_MAX would be 1E-11 and Y_MIN 1E-13)
(lengthOfRange <= X_MIN) && (lengthOfRange >= Y_MAX) ?
cout << "This value entered indicates that it is x\n" :
cout << "It is y";
Expressed this way if i input IE-11 it shows me "This value entered indicates ..." but will never show me it is y (understandably - overlap!)
The other way around would be expressing it this way:
(lengthOfRange <= X_MIN) && (lengthOfRange != Y_MAX) ?
cout << "This value entered indicates that it is x\n" :
cout << "It is y";
The output would always be "... It is y ..." (Same difference - overlap!) There is no other determining factor that would tell range is x or y coming in to play there as of right now.
...
if (lengthOfRange <= X_MIN) && (lengthOfRange == Y_MAX)
{
cout << "The input indicates that it could be either x or y\n";
}
...
Even if i were to solve the problem in a way such as defining the range with different values, would in the end lead to the very same problem. I COULD define MIN and MAX as constants in lengthOfFrequency, which is totally different, bit then i would have to say: lengthOfFrequency = 1E-11; and voila same problem once again. 1 input 2 ranges that are technically different, getting the same one and only correct value in E-notation.
Is there a way around this without involving to simply say input is either x || y? Which it is technically of course, and if it were to be solved physically there are ways of telling it apart that 1E-11 is not 1E-11 though it is. (I hope i make sense here). But, again, ... is there such way, and how would i go about writing it? (Not asking for code specifically though it would be highly welcome, just a pointer in the right direction.) Or should i rather go with saying input is either x || y?
Thanks in advance for any answer!
**Minimum Complete Code:**
#include <iostream>
using std::cout;
using std::cin;
int main()
{
/* Constants for ranges, min and max */
const double X_RAYS_MIN = 1E-13,
X_RAYS_MAX = 1E-11,
Y_RAYS_MIN = 1E-11,
Y_RAYS_MAX = 1E-8,
Z_RAYS_MIN = 1E-7,
Z_RAYS_MAX = 3.8E-7;
double lengthOfRange;
/* Test output and validation */
cout << "Enter value in scientifc notation: ";
cin >> lengthOfRange;
/* X_RAYS_MIN < is 1E-14, 1E-15, 1E-16 etc. > 1E-12, 1E-11 etc.. */
if (lengthOfRange >= X_RAYS_MIN && lengthOfRange <= X_RAYS_MAX)
{
cout << "X_RAYS\n";
}
else if (lengthOfRange >= Y_RAYS_MIN && lengthOfRange <= Y_RAYS_MAX)
{
cout << "Y_RAYS\n";
}
system("pause");
return 0;
}
Output is: 1E-10 is Y_RAYS, 1E-9 is Y_RAYS, 1E-11 X_RAYS, 1E-12 X_RAYS
Somehow i found the solution for my problem myself without going any roundabout ways ... By hovering over the 1E-13:
X_RAYS_MIN = 1E-13
VS showed me 1.(numberofzeros)3E-13, and guess what ... if instead the input for 1E-11 is 2E-11, the output for X_RAYS becomes Y_RAYS ... so the problem "magically" solved itself ... lucky me i guess ... :)

need understanding of while loop condition (see comment)

while (x >= 1000)
{
cout << "M";
x -= 1000;
}
Can someone explain to me how this while loop works? I understand the condition is for x is greater or equal to 1000, it will print out 'M'.
The part after that is what I actually don't understand, is it saying that it will keep subtracting a thousand from X and keep printing until the condition is false?
Yes, that is exactly what it will do.
This translates roughly into:
While x is greater than or equal to 1000, do what is in the code block (over and over until the condition fails)
The code block then prints M and sets x equal to itself minus 1000. (x -= 1000 is the same as x = x - 1000
Hypothetical:
x = 3000
x is greater than 1000
print M
x is set to 2000
loop resets and checks x...passes test
print M
x is set to 1000
loop resets and checks x...passes test because of = portion
print M
x is set to 0
loop resets and checks x...fails
moves to the code after the while code block
while (x >= 1000) //x is greater than or equal to 1000
{ //executes loop if condition true, else the statement after the loop block
cout << "M"; // print M
x -= 1000; // x = x-1000
} //goes back to condition checking
You are right!
x-=1000;
is actually
x=x-1000;
Yes.
it saying that it will keep subtracting a thousand from X and keep printing until the condition is false
The program appears to be an inefficient way of writing
x %= 1000;
which is x = x%1000, where % is the modulus operator.
Your code reaches the same result by subsequent substraction, and stops when x<1000.

C++ reading a sequence of integers

gooday programers. I have to design a C++ program that reads a sequence of positive integer values that ends with zero and find the length of the longest increasing subsequence in the given sequence. For example, for the following
sequence of integer numbers:
1 2 3 4 5 2 3 4 1 2 5 6 8 9 1 2 3 0
the program should return 6
i have written my code which seems correct but for some reason is always returning zero, could someone please help me with this problem.
Here is my code:
#include <iostream>
using namespace std;
int main()
{
int x = 1; // note x is initialised as one so it can enter the while loop
int y = 0;
int n = 0;
while (x != 0) // users can enter a zero at end of input to say they have entered all their numbers
{
cout << "Enter sequence of numbers(0 to end): ";
cin >> x;
if (x == (y + 1)) // <<<<< i think for some reason this if statement if never happening
{
n = n + 1;
y = x;
}
else
{
n = 0;
}
}
cout << "longest sequence is: " << n << endl;
return 0;
}
In your program, you have made some assumptions, you need to validate them first.
That the subsequence always starts at 1
That the subsequence always increments by 1
If those are correct assumptions, then here are some tweaks
Move the cout outside of the loop
The canonical way in C++ of testing whether an input operation from a stream has worked, is simply test the stream in operation, i.e. if (cin >> x) {...}
Given the above, you can re-write your while loop to read in x and test that x != 0
If both above conditions hold, enter the loop
Now given the above assumptions, your first check is correct, however in the event the check fails, remember that the new subsequence starts at the current input number (value x), so there is no sense is setting n to 0.
Either way, y must always be current value of x.
If you make the above logic changes to your code, it should work.
In the last loop, your n=0 is execute before x != 0 is check, so it'll always return n = 0. This should work.
if(x == 0) {
break;
} else if (x > y ) {
...
} else {
...
}
You also need to reset your y variable when you come to the end of a sequence.
If you just want a list of increasing numbers, then your "if" condition is only testing that x is equal to one more than y. Change the condition to:
if (x > y) {
and you should have more luck.
You always return 0, because the last number that you read and process is 0 and, of course, never make x == (y + 1) comes true, so the last statement that its always executed before exiting the loop its n=0
Hope helps!
this is wrong logically:
if (x == (y + 1)) // <<<<< i think for some reason this if statement if never happening
{
Should be
if(x >= (y+1))
{
I think that there are more than one problem, the first and most important that you might have not understood the problem correctly. By the common definition of longest increasing subsequence, the result to that input would not be 6 but rather 8.
The problem is much more complex than the simple loop you are trying to implement and it is usually tackled with Dynamic Programming techniques.
On your particular code, you are trying to count in the if the length of the sequence for which each element is exactly the successor of the last read element. But if the next element is not in the sequence you reset the length to 0 (else { n = 0; }), which is what is giving your result. You should be keeping a max value that never gets reset back to 0, something like adding in the if block: max = std::max( max, n ); (or in pure C: max = (n > max? n : max );. Then the result will be that max value.