chris@mimsy.UUCP (Chris Torek) (01/30/89)
[followups redirected to comp.lang.misc] In article <8515@lanl.gov> jlg@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@mimsy.umd.edu Path: uunet!mimsy!chris
jlg@lanl.gov (Jim Giles) (01/31/89)
From article <15692@mimsy.UUCP>, by chris@mimsy.UUCP (Chris Torek): > [...] >>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). It's worse in the sense that the loop without a clear trip count calculation may not terminate at all! Consider the following: for (x=0.0; x<=1.0, x+=0.0000001) {...} The intent is for 10 million steps. But if IEEE single is used, the increment becomes a no-op at some point. An explicit trip count calculation would at least not exhibit this problem. Rounding during the divide step would probably select the wrong trip count - but it wouuld still select a finite one. (before you shout that a 10 million trip loop is an unrealistic example, I should point out that such things are standard fare around here.) > [...] > which in F77 can be written (I will use `WHILE' here for conciseness > and to avoid those blasted statement numbers) Why not use the Fortran 8x style DO - END DO pair: no statement labels there :-).> > [...] > 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. Here's where we part company in a big way. I oppose ANY language construct that requires the programmer to know internals about how the construct is performed. Both Fortran and C (and most everything else for that matter) already have too many such constructs. It is probable that a compiled language CAN'T be written with SOME such constructs - but let's keep them at a minimum. For example, it's bad enough that in the above example you really have to write: for (i=0, i<10000000, i++) { x=i*0.0000001; ...} Now, the relative error in the value x during execution remains fairly constant (rather than accumulating as in the incremented version). Many Fortran compilers actually implement DO loops with real limits in the above manner. The standard should really specify that this should be done so the user needn't worry about it. J. Giles Los Alamos
chris@mimsy.UUCP (Chris Torek) (02/19/89)
In article <8618@lanl.gov> jlg@lanl.gov (Jim Giles) writes: >Here's where we part company in a big way. I oppose ANY language construct >that requires the programmer to know internals about how the construct >is performed. I will agree that `dark corners' or ambiguities are problematical (and C is full of them, so that programmers must exercise restraint; alas, many do not). But the number of iterations of a loop had better not be a `dark corner'! If you cannot predict the trip count given the limits and increments, you have no business writing that loop in the first place! >.... Many Fortran compilers actually implement DO loops with real limits >in the above manner [avoiding accumulated roundoff errors]. The standard >should really specify that this should be done so the user needn't worry >about it. And if the standard says it, or just as importantly if it does *not*, programmers using the language should be aware of it! If the standard says that DO-loop trip counts depend on the phase of the moon, the programmer should be prepared to look out the window as necessary. -- In-Real-Life: Chris Torek, Univ of MD Comp Sci Dept (+1 301 454 7163) Domain: chris@mimsy.umd.edu Path: uunet!mimsy!chris