Re: help with c++ if test

  • From: "Littlefield, Tyler" <tyler@xxxxxxxxxxxxx>
  • To: programmingblind@xxxxxxxxxxxxx
  • Date: Wed, 09 Feb 2011 15:32:14 -0700

>for(i=0, j=0; (i/100)*j == 9801; i++, j=i%100);
This is clenaer than goto?
You've prooven how to optomize my code (and it prooved an interesting read), but that doesn't really say goto is bad. You've just taken my loop, made it into the beast above and it works. So while I'll concede part of the point, I still believe that just like everything else, goto is a tool. If you don't want to mess with that, it works perfectly fine. No, this wasn't a real-world example, because there are ways to get that easily enough, but coming up with real-world examples isn't my strongpoint. So, find ways around goto, if you -must- use them, but use them sparingly. If it's your program flow control, or you have more than a couple per project, things need to be rewritten.
On 2/9/2011 3:13 PM, Sina Bahram wrote:
Ok, a few things.

#1: this entire program could be condensed into a one liner, because the result 
is mathematical and is known everytime; however, let's just assume your 
condition is more complex than  the sum of two itnegers getting to 100, so that 
we can actually have some code to optimize.

So, let's examine what's going on.

Note, I'm ignoring any one time costs like initializing I and j, and all the 
other one time things.


We have an outer loop that loops 100 times, which means that there are 100 
comparisons performed.

We have an inner loop that loops 100 times, which means that there are 100 
additional comparisons per outer loop iteration.

we then have 1 more comparison performed each time because we have an if 
statement inside the inner loop.

so each time, we do one comparison for the outer loop, and 200 comparisons for 
the inner loop, because it's 100 for the inner loop and 100 additional 
comparisons for the if statement inside the inner loop. Which gives us 201 
comparisons per iteration.

Your program stops after one iteration of the outer loop, as well as a brief 
iteration a second time, but only resulting in a few more comparisons until j 
reaches 1.

To be exact, you do 201 comparisons the first time, then you do 1 more for the 
outer loop and now i=1, two more for the inner loop and now j=1, and then 2 
more for when j is 1 and you take the goto.

I might have messed up in there by 1, let's just call it at 205 comparisons, ok?

Another way of phrasing this is i*201+(j+1)*2

So you can imagine, if your condition was not i+j == 100, but something like 
i*j == 9801, where I and j would have to be 99, that would result in 
(99*201)+(99+1)*2 comparisons, which is roughly equal to 20,099 coparisons.

Now, let's get rid of the goto, and see what happens to our cost value for i=99 
and j=99.

Example 1:

#include<stdio.h>

int main()
{
int i, j;
for (i=0; i<  100; i++)
{
for (j=0; j<  100; j++)
{
if (i+j == 100)
{
printf("i: %d j: %d i+j: %d", i, j, i+j);
return 0;
}
}
}
return 0; // will never get called
}

As you can see, it's the exact same cost, with no goto. However, in a way, 
that's untrue to your example. What if you don't want to exit the method, but 
keep going, which is why you had a goto, in the first place.

Example 2:

If you don't mind, I used i*j == 9801, just so we can make the program run for 
longer, otherwise, there's like no point, but feel free to substitute back in 
i+j == 100, if you wish.

Here I've unrolled your inner loop and used C99 because reading C89 makes Sina 
sad.

#include<stdio.h>

int main()
{
for(int i=0; i<  10000; i++)
{
int j = i%100;
if((i/100)*j == 9801)
{
printf("i: %d j: %d i*j: %d", i/100, j, (i/100)*j);
break;
}
}

// do whatever you want here, if you like

return 0;
}

Vwalla, you now have only 2 comparisons per iteration for 9,999 itterations, 
and then one more comparison on the last loop, which only gives us 19,999 
comparisons, which is actually 100 comparisons less than last time, and there 
is no goto, and there is less work for your branch predictor, and there is less 
code space, and it's just better!

But wait! There's more! For only an additional easy payment of promising never 
to use goto, ever, ever, ever again in your natural life, we have this special 
offer!

Example 3:

#include<stdio.h>

int main()
{
int i, j;
for(i=0, j=0; (i/100)*j == 9801; i++, j=i%100);

printf("i: %d j: %d i*j: %d", i/100, j, (i/100)*j);

// do whatever you want here, if you like

return 0;
}

note, some compilers might optimize out that loop completely because it has no 
body, so instruct them not to, but in the real world, it's conceivable that 
this of course will not happen cuz you won't be doing such a simple arithmetic 
operation.


We are now down to only 10,000 comparisons, compared to the original 20,099. 
That's more than a 50% savings.

And, because I really, truly, cannot help myself!

Let's make this even more efficient, shall we?

Example 4:

Get rid of j, he's annoying, and nobody likes him.

#include<stdio.h>

int main()
{
int I;
for(i=0; (i/100)*(i%100) == 9801; i++);

printf("i: %d j: %d i*j: %d", i/100, i%100, (i/100)*(i%100));

// do whatever you want here, if you like

return 0;
}

There you go, 10K comparisons, no extra variable, faster performance, less 
register conjestion, happier branch prediction algorithm, and happier everyone 
for no use of goto.

Happy hacking

Take care,
Sina

-----Original Message-----
From: programmingblind-bounce@xxxxxxxxxxxxx 
[mailto:programmingblind-bounce@xxxxxxxxxxxxx] On Behalf Of Littlefield, Tyler
Sent: Wednesday, February 09, 2011 2:57 PM
To: programmingblind@xxxxxxxxxxxxx
Subject: Re: help with c++ if test

#include<stdio.h>
int main()
{
int i, j;
for (i=0; i<  100; i++)
{
for (j=0; j<  100; j++)
{
if (i+j == 100)
{
goto bottom;
}
}
}
bottom:
printf("i: %d j: %d i+j: %d", i, j, i+j);
return 0;
}
i = 1 j = 99 i+j 100.
On 2/9/2011 12:42 PM, Sina Bahram wrote:
Please send out the version of this code using a goto.

Take care,
Sina

-----Original Message-----
From: programmingblind-bounce@xxxxxxxxxxxxx 
[mailto:programmingblind-bounce@xxxxxxxxxxxxx] On Behalf Of Littlefield, Tyler
Sent: Wednesday, February 09, 2011 2:40 PM
To: programmingblind@xxxxxxxxxxxxx
Subject: Re: help with c++ if test

Not exactly. Take this for example:
int i = 0;
int j = 0;
int check = 1;
for (; i<   100&&   check; i++)
{
for (;j<   100; j++)
{
if (i+j == 100)
{
check = 0;
break;
}
}
}
now, that's doing an extra 100 comparisons (1 per iteration of the top
loop), where as you could just jump to a label and be done with it.
They -are- messy, they shouldn't be used everywhere, but they are a tool
to be used. I'm not really understanding the whole point of avoiding
them at all cost just because they're supposed to be bad. You have one
jump as opposed to 100 comparisons. If you like the 100 comparisons, so
be it. But there haven't been any valid reasons beyond "this creates bad
code," which I'll fully agree with in a lot of places. Goto should be
used sparingly, but as I said, I think goto is a tool, just like
anything else. A good coder will know when to make use of his tools, and
when to use better ones, as well as the tradeoffs of using tool A over
tool B.
On 2/9/2011 12:32 PM, Sina Bahram wrote:
I disagree about goto. Every example you've provided, Ty, there's been a better 
way to do it without goto.

Take care,
Sina


-----Original Message-----
From: programmingblind-bounce@xxxxxxxxxxxxx 
[mailto:programmingblind-bounce@xxxxxxxxxxxxx] On Behalf Of Littlefield, Tyler
Sent: Wednesday, February 09, 2011 2:14 PM
To: programmingblind@xxxxxxxxxxxxx
Subject: Re: help with c++ if test

Sina:
You could write it as Lex suggested, and just use a variable to check,
whichever solution you choose, it would work fine. Here's my point. Goto
is a tool. Like any tool in c/c++, it can be abused, but it can also be
useful to jump out of code, or when you don't want code replication. if
(!foo()) goto handleerror; if (!bar()) goto handleerror. I've used
this... once, possibly twice when the code for handling such an error
was kind of long and complex and I didn't want to try to pass everything
through a function to accomplish the same thing.
On 2/9/2011 12:06 PM, Sina Bahram wrote:
Here's a new rule.

Assume that goto does not exist. Just get rid of it. It's gone, *waves hands*.

Now, rewrite that code.

Take care,
Sina



-----Original Message-----
From: programmingblind-bounce@xxxxxxxxxxxxx 
[mailto:programmingblind-bounce@xxxxxxxxxxxxx] On Behalf Of Kristoffer 
Gustafsson
Sent: Wednesday, February 09, 2011 2:03 PM
To: programmingblind@xxxxxxxxxxxxx
Subject: Re: help with c++ if test

Hi.
ok, some code of mine looks like
#include<iostream>
int main()
{
string test;
cin>>test;
if (test=="fine" goto good;

good:
cout<<"it works!";
return 0;
}

I try this and I get expected `before goto.
What can be wrong?
/Kristoffer

----- Original Message -----
From: "Ken Perry"<whistler@xxxxxxxxxxxxx>
To:<programmingblind@xxxxxxxxxxxxx>
Sent: Wednesday, February 09, 2011 7:53 PM
Subject: RE: help with c++ if test


It is easy to do text adventures or any programming without goto.  Note that
my commercial mud has 0 goto statements in it.  Now all classes in college
will tell you to avoid goto unless you're dealing with programming operating
systems and need to be able to jump out of scope.  Which is one of the
reasons you do not want to use goto.  For example

     Void myfunc(){
Goto two;
}

Void myFunc2(){
Two:

}

You can actually jump function to function with goto which breaks all kinds
of things in functional and object oriented programming.  Now that is
necessary some times when doing error handling.  The truth is though if your
coding your own application you really should never need goto.   If you find
yourself using goto you have probably designed your program wrong.

I will not go into a deep why or why not to use it because if your thinking
you cannot create an adventure game without it you will not understand a lot
of my explanation.  I think you need to go through some tutorials on c or
c++ which ever one you're using because you have a lot to learn.



Ken

-----Original Message-----
From: programmingblind-bounce@xxxxxxxxxxxxx
[mailto:programmingblind-bounce@xxxxxxxxxxxxx] On Behalf Of Kristoffer
Gustafsson
Sent: Wednesday, February 09, 2011 1:41 PM
To: programmingblind@xxxxxxxxxxxxx
Subject: Re: help with c++ if test

Hi.
Without goto it would be very hard to do text adventures.
I don't think it can be done, or can it?
Also, if I want my program to exit instead of continuing, how do I do?
I mean for example, if I die in an adventure, I want to exit the program at
that time, not continue the game.
/Kristoffer
----- Original Message -----
From: "Littlefield, Tyler"<tyler@xxxxxxxxxxxxx>
To:<programmingblind@xxxxxxxxxxxxx>
Sent: Wednesday, February 09, 2011 7:28 PM
Subject: Re: help with c++ if test


That produces all sorts of problems. jumping to the bottom of a loop is no
problem with a goto, and it avoids issues with your exiting variable. it's
also quicker, because you just jump to the bottom. otherwise you may
break, but it's still going to have to do one more check (two, actually,
depending on how the compiler does things) to see if exiting is false.
On 2/9/2011 11:23 AM, Lex wrote:
09.02.2011 20:17, Littlefield, Tyler пишет:
really really highly recommend you avoid goto. This isn't basic, and
they're not very useful except for in some odd cases, far and few
between. Such as jumping out of two nested loops like so:
int i, j;
for (i = 0; i<     100; i++)
{
for (j = 0; j<     100; j++)
{
if (i+j == 100)
goto botttom;
}
}
bottom:
//do something here
Actually, effect you're trying to achieve is more correctly by the
conditional variable (at least in terms of procedural programming):
bool exiting=false;
for (i = 0; i<     100&&     !exiting; i++)
{
for (j = 0; j<     100&&     !exiting; j++)
{
if (i+j == 100)
exiting=true;
}
}


or may be even
for (j = 0; j<     100; j++)
{
if (i+j == 100)
{
exiting=true;
break;
}
}
}


Lex

__________
View the list's information and change your settings at
//www.freelists.org/list/programmingblind


--

Thanks,
Ty

__________
View the list's information and change your settings at
//www.freelists.org/list/programmingblind
__________
View the list's information and change your settings at
//www.freelists.org/list/programmingblind

__________
View the list's information and change your settings at
//www.freelists.org/list/programmingblind

__________
View the list's information and change your settings at
//www.freelists.org/list/programmingblind

__________
View the list's information and change your settings at
//www.freelists.org/list/programmingblind





--

Thanks,
Ty

__________
View the list's information and change your settings at //www.freelists.org/list/programmingblind

Other related posts: