"for" loops

Chris Torek chris at mimsy.UUCP
Mon Jan 30 04:00:46 AEST 1989


[followups redirected to comp.lang.misc]
In article <8515 at lanl.gov> jlg at lanl.gov (Jim Giles) writes:
>[the floating point DO-loop construct] is considered a mistake because
>the standard doesn't make any constraints on the accuracy of floating-
>point arithmetic.  So the trip count on a loop with floating-point
>limits is not well-defined.

(True in both C and FORTRAN.)

>The C for-loop is even worse in this regard - the trip count is not
>precomputed.

That this is worse is mere opinion (or perhaps contentiousness).

>Consider the following:
>
>      for (x=0.0; x<=1.0, x+=0.1) {...}

Or consider:

	tripcount = (int)((1.0-0.0)/0.1) + 1;
		/* or should this be rounded rather than truncated? */
		/* (I have no F77 reference handy, sorry) */
	for (x = 0.0; --tripcount >= 0; x += 0.1) ...

which (in theory) does what the F77 construct

	DO label X = 0.0, 1.0, 0.1

does.  But suppose the task is to find the accumulated error?

	for (i = 0, x = 0.0; x <= 1.0; i++, x += 0.1)
		/* void */;
	printf("[0.0,1.0] count took %d steps; x-1.0=%g\n", i, x - 1.0);

which in F77 can be written (I will use `WHILE' here for conciseness
and to avoid those blasted statement numbers)

	X = 0.0
	I = 0
	WHILE (X .LE. 1.0) DO
	    X = X + 0.1
	    I = I + 1
	ENDWHILE
		! (I forget whether PRINT * puts spaces around numbers)
	PRINT *, '[0.0,1.0] count took', I, 'steps; x-1.0=', X-1.0

Not really that different after all (although the FORTRAN version is
in ugly uppercase :-) ).

>The value of x for each trip through the loop is a sum of 0.1+ ... +0.1,
>a value which suffers round-off or truncation on each successive add.  
>If the four operations in the computation of the Fortran trip count
>lead to ambiguous results, the 11 adds in the above are even worse.

Any programmer worth his pay is aware of the method by which the trip
count is determined, and will write the appropriate code in the appropriate
situation.  It is true that situations demanding floating point loop
counters are rare.

In any case, the generalised `for' loop construct in C is very
worthwhile, although a specialised precomputed-count loop construct (a
la most other Algol/FORTRANnish languages) might be nice.  C's `for'
fits a number of situations well, such as

	for (p = head; p != NULL; p = p->next)

for simple list traversal, or

	for (p = head.next; p != &head; p = p->next)

for circular queues, or

	for (x = init; fn1(x) < fn2(x); x = fn3(x))

for essentially arbitrary stepping around a graph of two functions
looking for a crossover.  For loops with a fixed iteration limit,
a construct like

	for i in [1..N) do

is often better, since it is clearer and allows the compiler to use
shadowing or downcounts or whatnot without requiring it to determine
that the limit is in fact fixed.  It is sometimes worthwhile in C to
recode something like

	for (i = 1; i < f(); i++)	/* where f() is a pure function */

as

	for (j = f(), i = 1; --j > 0; i++)

or (clearer but sometimes slower)

	for (i = 1, j = f(); i < j; i++)

and this sort of nonsense is really best left to the compiler.
-- 
In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163)
Domain:	chris at mimsy.umd.edu	Path:	uunet!mimsy!chris



More information about the Comp.lang.c mailing list