Correct C++ tutorial part 3 "Intro to loops" available (Windows, mingw/msvc/std)

A

Alf P. Steinbach

The third part of my attempted Correct C++ tutorial is now available,
although for now only in Word format (use free Open Office if no Word),
and also, it's not yet been extensively reviewed -- comments welcome!

"Intro to loops"
<url: http://home.no.net/dubjai/win32cpptut/w32cpptut_01_03.doc>

As before I expect that here's mental food and technical points that
we can strongly disagree about, for both newbie and the experienced.

And as before the point of inviting comments is to _fix_ anything
incorrect, or the presentation, or whatever; your input is valuable.

The first two parts, "Hello, world!" and "Variables", are available
both as Word docs and (now reasonably structured! ;-)) HTML at

<url: http://home.no.net/dubjai/win32cpptut/html/>

Again, re part 2, thanks to Stephan Brönniman for helping with the
conversion from Word to HTML, and helpful comments & corrections.


[I inadvertently posted this message to comp.std.c++: darn that mouse!
If any of the moderators read this and can cancel that, please.]
 
B

Bogdan Sintoma

Hi Alf,

In the chapter 8 maybe: "Always use an integral type such as int for a
loop control variable" is 'to strong'. I think to something like:
"chose the desired precision when dealing with floats and avoid 'equal'
operators".

Another pitfall could be: for( unsigned int i = 5; i >= 0; --i ) { ...
}

Best regards,
Bogdan Sintoma
 
A

Alf P. Steinbach

* Alf P. Steinbach:
The third part of my attempted Correct C++ tutorial is now available,
although for now only in Word format (use free Open Office if no Word),
and also, it's not yet been extensively reviewed -- comments welcome!

"Intro to loops"
<url: http://home.no.net/dubjai/win32cpptut/w32cpptut_01_03.doc>

As before I expect that here's mental food and technical points that
we can strongly disagree about, for both newbie and the experienced.

And as before the point of inviting comments is to _fix_ anything
incorrect, or the presentation, or whatever; your input is valuable.

Well, I discovered one Big Blunder myself! :-o

In section 4, "[Pitfall:] Using assignment instead of comparision",
I described an if-condition as accepting non-bool values because it
converted bool to numerical zero / non-zero. That was correct as an
effective belief, and may be the way it is in C, but it's not how it
actually works in C++. In C++ the same _effect_ is achieved by having
implicit conversion of non-bool values (zero, non-zero) to bool.

Now corrected...
 
A

Alf P. Steinbach

* Bogdan Sintoma:
Hi Alf,

In the chapter 8 maybe: "Always use an integral type such as int for a
loop control variable" is 'to strong'. I think to something like:
"chose the desired precision when dealing with floats and avoid 'equal'
operators".

Well, here's my reasoning:

* If you use e.g. 'double' as a loop control variable (counter), you
either use integer update (e.g. increment) or non-integer update.

* If you use integer update you should use integer type for the
variable.

* If you use non-integer update you're in trouble, and/or are
doing things in a needlessly complicated way; either way the
solution is to use integer type for the loop control variable.

Additionally, it would take much text to explain how to compare
floating point values "safely", and what degree of safety can be
achieved (it's an advanced topic one can write a whole book about...).

Does this make sense?


Another pitfall could be: for( unsigned int i = 5; i >= 0; --i ) { ...
}

Yes, thanks.

My thinking here has been to introduce only the bare minimum of
_general_ functionality, not things that are really only optimization or
only useful in special cases, and so no 'unsigned' yet, only 'int'.

But perhaps that pitfall is so common that it deserves to be mentioned
even at this early stage?
 
B

Bogdan Sintoma

Alf said:
* Bogdan Sintoma:

Well, here's my reasoning:

* If you use e.g. 'double' as a loop control variable (counter), you
either use integer update (e.g. increment) or non-integer update.
Well, it could be situations when a loop control variable isn't really
a counter. Double as control variable and increment (or decrement)
isn't a smart choice :) (GotW #67 ;) )
* If you use integer update you should use integer type for the
variable. Agree.


* If you use non-integer update you're in trouble, and/or are
doing things in a needlessly complicated way; either way the
solution is to use integer type for the loop control variable.
Let's say that you have to simulate some process. And this process must
run until some variable (e.g some cumulated errors) exceed some level.
Using this variable as a loop control variable could be more
appropriate than converting (rounding) it and the limit to some integer
value.

Anyway, I just wand to say something like "never say never" :)
Additionally, it would take much text to explain how to compare
floating point values "safely", and what degree of safety can be
achieved (it's an advanced topic one can write a whole book about...).
That's true.
Does this make sense?



Yes, thanks.

My thinking here has been to introduce only the bare minimum of
_general_ functionality, not things that are really only optimization or
only useful in special cases, and so no 'unsigned' yet, only 'int'.

But perhaps that pitfall is so common that it deserves to be mentioned
even at this early stage?

Not if it is just me that say so :).
But, size_t is unsigned, isn't it? Should I write the pitfall as:
for( vector<int>::size_type i = (v.size()-1); i >= 0; --i ){...} ? :)
 
C

Computer Whizz

Alf P. Steinbach said:
The third part of my attempted Correct C++ tutorial is now available,
although for now only in Word format (use free Open Office if no Word),
and also, it's not yet been extensively reviewed -- comments welcome!

"Intro to loops"
<url: http://home.no.net/dubjai/win32cpptut/w32cpptut_01_03.doc>

As before I expect that here's mental food and technical points that
we can strongly disagree about, for both newbie and the experienced.

And as before the point of inviting comments is to _fix_ anything
incorrect, or the presentation, or whatever; your input is valuable.

The first two parts, "Hello, world!" and "Variables", are available
both as Word docs and (now reasonably structured! ;-)) HTML at

<url: http://home.no.net/dubjai/win32cpptut/html/>

Again, re part 2, thanks to Stephan Brvnniman for helping with the
conversion from Word to HTML, and helpful comments & corrections.


[I inadvertently posted this message to comp.std.c++: darn that mouse!
If any of the moderators read this and can cancel that, please.]

--
A: Because it messes up the order in which people normally read text.
Q: Why is it such a bad thing?
A: Top-posting.
Q: What is the most annoying thing on usenet and in e-mail?

May I ask why you chose to do loops and then the IF statement, instead of
the other way around?

IMO it would have been more clear to explain IF, the go onto a loop, then
briefly do IF and then go into more detail later on (in your next part I
presume).

I find these tutorials very nice, and reading through them has been very
pleasant - thank you for writing these!
 
A

Alf P. Steinbach

* Bogdan Sintoma:
Well, it could be situations when a loop control variable isn't really
a counter.

Does it matter whether it counts or not?

Double as control variable and increment (or decrement)
isn't a smart choice :) (GotW #67 ;) )

At first reading that seems like we're in agreement, but on second
reading I'm not sure I grok that statement -- and what's
<url: http://www.gotw.ca/gotw/067.htm> got to do with this?


[snip]
Let's say that you have to simulate some process. And this process must
run until some variable (e.g some cumulated errors) exceed some level.
Using this variable as a loop control variable could be more
appropriate than converting (rounding) it and the limit to some integer
value.

One example could be to iteratively determine the square root of n,
using a 'double' variable 'root' and binary search. But now I don't
think of that variable as a loop control variable. Trying to pin down
what I mean, which I think is the general accepted meaning: in each
iteration except the first the value of a loop control variable depends
(only) on the previous value of that variable, the values in different
iterations except possibly the last one are different, and the loop
condition depends on that variable and possibly more.

The WikiPedia definition of 'loop counter' is somewhat similar, at
<url: http://en.wikipedia.org/wiki/Loop_counter>, but I don't like using
the word "counter" which implies a more restricted meaning.

On the other hand, using the Newton/Raphson algorithm 'root' would
qualify as a loop control variable, with both the above definitions.

So I think you're right that my advice excludes a whole general class
of useful 'double' loop control variables.

What could be a good way to include this information in the text,
keeping it reasonably short and novice-level?


[snip]
But, size_t is unsigned, isn't it? Should I write the pitfall as:
for( vector<int>::size_type i = (v.size()-1); i >= 0; --i ){...} ? :)

Thinking about that pitfall it's part of a more general pitfall, namely
assuming integer values exist outside the defined range.

I think it will have to wait till a general discussion of that.

If, when, I get to that... :)
 
A

Alf P. Steinbach

* Computer Whizz:
May I ask why you chose to do loops and then the IF statement, instead of
the other way around?

Well I didn't... ;-) It's like the resolution of a circular class
dependency A <-> B by introducing abstract base classes A' and B', and
then A <- (A' + B'), B <- (A' + B'), where "x <- y" means x depends on
y. What I did was to first introduce a raw infinite loop (base class
A'), which serves to introduce an unconditional jump which I think is
the most basic and easiest-to-comprehend form, and then a simple 'if'
(base class B'), which serves to introduce a conditional jump.

After that a more full discussion of loops (concrete class A), done
first because loops allow you to do interesting things.

The next part tackles decisions in general (concrete class B).


[snip]
I find these tutorials very nice, and reading through them has been very
pleasant - thank you for writing these!

Thank _you_.
 
B

Bogdan Sintoma

Alf said:
Does it matter whether it counts or not?
Maybe, please see below.
At first reading that seems like we're in agreement, but on second
reading I'm not sure I grok that statement -- and what's
<url: http://www.gotw.ca/gotw/067.htm> got to do with this?

You mention increment and 'doubles'. I just want to point out that
there are float implementation that cannot exactly represent all the
integer values from certain interval.
And, yes, we are in agreement for 'count-controlled loops'.

[snip]
One example could be to iteratively determine the square root of n,
using a 'double' variable 'root' and binary search. But now I don't
think of that variable as a loop control variable. Trying to pin down
what I mean, which I think is the general accepted meaning: in each
iteration except the first the value of a loop control variable depends
(only) on the previous value of that variable, the values in different
iterations except possibly the last one are different, and the loop
condition depends on that variable and possibly more.

The WikiPedia definition of 'loop counter' is somewhat similar, at
<url: http://en.wikipedia.org/wiki/Loop_counter>, but I don't like using
the word "counter" which implies a more restricted meaning.
Yes, that's true, but let me cite the same source:
http://en.wikipedia.org/wiki/Conditional_branching#Loops
"A loop is a sequence of statements which is specified once but which
may be carried out several times in succession. The code "inside" the
loop (the body of the loop, shown below as xxx) is obeyed a specified
number of times, or once for each of a collection of items, or until
some condition is met."
And further 'count-controlled' and 'condition-controlled' loops are
defined.
The c++ 'for' statement can be used in both cases.
(Actually "the standard" - 6.5.3.1 - define the 'for' statement in
equivalence with the 'while' statement)
On the other hand, using the Newton/Raphson algorithm 'root' would
qualify as a loop control variable, with both the above definitions.

So I think you're right that my advice excludes a whole general class
of useful 'double' loop control variables.
Thanks :)
What could be a good way to include this information in the text,
keeping it reasonably short and novice-level?
Well, that's not so easy :).
What about: "Don't use floating point types as loops control variable,
unless you really know what you are doing." :)
[snip]
But, size_t is unsigned, isn't it? Should I write the pitfall as:
for( vector<int>::size_type i = (v.size()-1); i >= 0; --i ){...} ?
:)

Thinking about that pitfall it's part of a more general pitfall, namely
assuming integer values exist outside the defined range.
Agree.

I think it will have to wait till a general discussion of that.

If, when, I get to that... :)
Just erase the "if" ;).

Best regards,
Bogdan
 
A

Alf P. Steinbach

* Bogdan Sintoma:
What about: "Don't use floating point types as loops control variable,
unless you really know what you are doing." :)

Done.

Thanks,

- Alf
 
A

Attila Feher

Alf said:
* Bogdan Sintoma:

Well, here's my reasoning:

* If you use e.g. 'double' as a loop control variable (counter), you
either use integer update (e.g. increment) or non-integer update.

Yeah. And you use either C++ or not to write it. ;-)
* If you use integer update you should use integer type for the
variable.

Why? You have introduced your lines with the word reasoning, but I see no
reason told for this statement.
* If you use non-integer update you're in trouble, and/or are
doing things in a needlessly complicated way; either way the
solution is to use integer type for the loop control variable.

Again, no reasoning. Using floating point numbers where floating point
operations are needed is (IMHO) not needlessly complicated for two reasons:
1.) Read the beginning of the sentence, 2.) using floating point is only
complicated until you learn it.
Additionally, it would take much text to explain how to compare
floating point values "safely", and what degree of safety can be
achieved (it's an advanced topic one can write a whole book about...).

That is the only reasoning in your text. Which suggests that instead of
making up a rule which is not supported by any real arguments (original
says: "Always use an integral type such as int for a loop control variable",
so it effectively rules out iterators as well as a billion other things) why
not tell simply what you have said above: floating point arithmetics is a
topic of its own, not something which belongs to a beginner's tutorial?
Does this make sense?

Only the last sentence. The rest makjes sense too, as an opinion, but not
as reasoning. ;-)
Yes, thanks.

My thinking here has been to introduce only the bare minimum of
_general_ functionality, not things that are really only optimization
or only useful in special cases, and so no 'unsigned' yet, only 'int'.

But perhaps that pitfall is so common that it deserves to be mentioned
even at this early stage?

There is somewhere on the net (was it Stroustrups pages?) a paper on why not
ot use unsigned variables for most of the things. So probably you want to
introduce that opportunity later, so people don't fly off course on a
tangent and start playing around with unsigned values.
 
A

Alf P. Steinbach

* Attila Feher:
Yeah. And you use either C++ or not to write it. ;-)

That's the context: a numeric loop control variable, with two mutually
excluding and exhaustive possibilities then discussed.

Why? You have introduced your lines with the word reasoning, but I see no
reason told for this statement.

It seems to boil down to two issues: why it's not a good idea to use a
misleading type (maintainability), and whether a floating point type can
always represent all values of an integral type exactly (technical).

Again, no reasoning. Using floating point numbers where floating point
operations are needed is (IMHO) not needlessly complicated for two reasons:
1.) Read the beginning of the sentence, 2.) using floating point is only
complicated until you learn it.

Yes, to the latter two sentences. I wonder whether you are happy with
the resolution of that issue as it turned out in the rest of the thread?
That is, adding the parenthetical expression "unless you really know
what you're doing"?

That is the only reasoning in your text. Which suggests that instead of
making up a rule which is not supported by any real arguments (original
says: "Always use an integral type such as int for a loop control variable",
so it effectively rules out iterators as well as a billion other things) why
not tell simply what you have said above: floating point arithmetics is a
topic of its own, not something which belongs to a beginner's tutorial?

Iterators and pointers as loop control variables is a good point,
thanks.

The discussion above was trapped in the implicit context of numeric loop
control variables.

Possibly I should add the word "numeric" in the advice. But I think it
would then hang in thin air, not related to the rest of the discussion.
Suggestions?
 
A

Attila Feher

Alf P. Steinbach wrote:
[SNIP]
It seems to boil down to two issues: why it's not a good idea to use a
misleading type (maintainability), and whether a floating point type
can always represent all values of an integral type exactly
(technical).

Why would a floating point type misleading if I need a floating point value?
Furthermore - on the same note - why would I care about it representing or
not integer values, if I needed a floating point one in the first place?

[SNIP]
Yes, to the latter two sentences. I wonder whether you are happy with
the resolution of that issue as it turned out in the rest of the
thread? That is, adding the parenthetical expression "unless you
really know what you're doing"?

That is one way to put it. :) But I guess there is another and probably
more important reason/cause: do you need a floating point iteration or not?
:) And then comes the know what you do, do what you know. ;-)

[SNIP]
Iterators and pointers as loop control variables is a good point,
thanks.

No problemo. :)
The discussion above was trapped in the implicit context of numeric
loop control variables.

And it possibly should for that very-beginner part, but IMHO the rule itself
may need to be worded differently. So that it suggests to the reader that
the rules is supposed to say: do not use floating point unless you really
need it (IMHO this goes not only for loops), so basically tell what is
wrong, instead of identifying what is right. Because limiting the possible
types (in this case/stage) will rule out valid cases, valid cases you did
not introduce yet for a reason.
Possibly I should add the word "numeric" in the advice. But I think
it would then hang in thin air, not related to the rest of the
discussion. Suggestions?

What I wrote above could probably be worded.

Loops can do (at least) counting and iterating, not taking into account the
"abuses" of them, like when a do {} while(0); loop (with breaks inside) is
used instead of a local try-catch...

So the loop variable in those non-abuse cases can mean a numeric value
(counting), and index value (addressing into containers using the array
access) or an iterator. A loop walking a linked list (with the loop
variable being a pointer to one list element) is (IMHO) a special case of
iteration.

My point is: there can be numerous other (legal and "good design") uses of
loops, which the current rule rules out. If the rule could be worded to
only say what not to do, the "unknown number of other legal uses" would not
be affected by it.
 
A

Alf P. Steinbach

* Attila Feher:
If the rule could be worded to only say what not to do, the
"unknown number of other legal uses" would not be affected by it.

Done.

New wording:

<quote>
That's partly why the program uses the integer type int for the counter,
instead of double (thanks to Bogdan Sintoma and Attila Feher for good advice
concerning the wording here):

* Don't use a floating point type such as double for a loop control variable
(unless you really know what you're doing).

If you do use e.g. double you'll get accumulated rounding errors, and
probably end up with a program that loops one less time than it "should"
and results that are very wildly off the mark.
</quote>

Thanks,

- Alf
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top