Code Comments
Programming Forum and web based access to our favorite programming groups.> Yes! You are expecting calculations done with floating point numbers > to be EXACT. Such calculations are actually approximate. Each > operation has a small quantity of error built in. That's the nature of > floating point. No I am not. I understand how (binary) floating points are used to represent actual (decimal) numbers. If I thought they were exact, I wouldn't be asking how to round it off properly so that the errors are not shown. However I have since found where I went wrong. I was using double precision Speed, Azimuth, V Azimuth = 90. parameter(Pi = 3.141592653589793238d0) V = Speed * cos(Azimuth * Pi / 180.) print *, V The problem with the unusually large value of -4.37113886E-06 arose because I didn't declare Pi to be double precision, even though I assigned a double precision value to it. Thus rounding off its value to real. I realized that after studying Richard Maine's short program, which gave me a smaller answer of 6.12303177E-17 in the expected range of precision. Now that I have a value in the range E-17 instead of E-06, I can now use F15.12 to round it off! My question has been answered. Thanks to all who helped!
Post Follow-up to this messageBamm wrote: (snip) > However I have since found where I went wrong. I was using > double precision Speed, Azimuth, V > Azimuth = 90. > parameter(Pi = 3.141592653589793238d0) > V = Speed * cos(Azimuth * Pi / 180.) > print *, V > The problem with the unusually large value of -4.37113886E-06 arose > because I didn't declare Pi to be double precision, even though I > assigned a double precision value to it. This problem might be more likely to occur to ex-C programmers. C uses #define is places where Fortran uses PARAMETER, but #define is typeless. It might be nice for compilers to give a warning in this case. There are enough reasons to assign double precision values to single precision variables that I wouldn't want a default warning in that case. I don't believe the same is true for PARAMETER. -- glen
Post Follow-up to this messageglen herrmannsfeldt <gah@ugcs.caltech.edu> writes: > Bamm wrote: > (snip) > > > > > This problem might be more likely to occur to ex-C programmers. > > C uses #define is places where Fortran uses PARAMETER, > but #define is typeless. There's a little more to it than that. In C, the literal constant "0.1" has type double precision, in Fortran, the literal constant "0.1" has type single precision. So double x = 0.1; in C gives x the double precision value +1. 6000000000000000888178419700125232338905 33447265625 / 16 whereas DOUBLE PRECISION X X = 0.1 in Fortran gives X the single precision value +1.60000002384185791015625 / 16 Actually, now that I look at it, the OP actually had the opposite problem, analogous to X = 0.1D0 where X is implicitly typed default real (single precision), but the literal constant has type double precision. Chip -- Charles M. "Chip" Coldwell "Turn on, log in, tune out" GPG Key ID: 852E052F GPG Key Fingerprint: 77E5 2B51 4907 F08A 7E92 DE80 AFA9 9A8F 852E 052F
Post Follow-up to this messageCharles Coldwell wrote: (snip, I wrote) > There's a little more to it than that. In C, the literal constant "0.1" > has type double precision, in Fortran, the literal constant "0.1" has > type single precision. So (snip) > Actually, now that I look at it, the OP actually had the opposite > problem, analogous to > X = 0.1D0 > where X is implicitly typed default real (single precision), but the > literal constant has type double precision. Well, the OP had: double precision Speed, Azimuth, V Azimuth = 90. parameter(Pi = 3.141592653589793238d0) V = Speed * cos(Azimuth * Pi / 180.) A double precision constant as a single precision PARAMETER used in a double precision expression. The C equivalent #define PI 3.141592653589793238 as you say, the constant is double precision (without an f), but PI itself is typeless. You can do things like: #define ABS(x,y) ((x)>(y)?(x):(y)) as a typeless absolute value in C89. (It wont' work for complex types in C99.) -- glen
Post Follow-up to this messageglen herrmannsfeldt wrote: > Charles Coldwell wrote: > (snip, I wrote) > > (snip) > > > > > Well, the OP had: > > double precision Speed, Azimuth, V > Azimuth = 90. > parameter(Pi = 3.141592653589793238d0) > V = Speed * cos(Azimuth * Pi / 180.) > > A double precision constant as a single precision PARAMETER > used in a double precision expression. The C equivalent > > #define PI 3.141592653589793238 > > as you say, the constant is double precision (without an f), > but PI itself is typeless. You can do things like: > > #define ABS(x,y) ((x)>(y)?(x):(y)) > > as a typeless absolute value in C89. (It wont' work for complex > types in C99.) I think you mean MIN instead of ABS. ABS would be something like: #define ABS(x) ((x) >= 0 ? (x) : -(x)) Unlike a FORTRAN statement function, which this vaguely resembles, macros that use an argument in more than one place do weird things when passed an expression with side effects, e.g., ABS(x++). Louis
Post Follow-up to this messageLouis Krupp wrote: (snip) > I think you mean MIN instead of ABS. ABS would be something like: > #define ABS(x) ((x) >= 0 ? (x) : -(x)) > Unlike a FORTRAN statement function, which this vaguely resembles, > macros that use an argument in more than one place do weird things when > passed an expression with side effects, e.g., ABS(x++). Yes, both are often written as macros in C. I was thinking about both and wrote something in between. The side effects are something to remember, but it doesn't take too long as long as you know it is a macro. -- glen
Post Follow-up to this message"glen herrmannsfeldt" <gah@ugcs.caltech.edu> wrote in message news:n9idnTScSJC6423anZ2dnUVZ_qninZ2d@co mcast.com... > Louis Krupp wrote: > (snip) > > > > > Yes, both are often written as macros in C. I was thinking > about both and wrote something in between. > > The side effects are something to remember, but it doesn't > take too long as long as you know it is a macro. You have ped (sp) my interest here. PRE00-A. Prefer inline functions to macros The claim that 'macros are dangerous' can, to a certain extent, be justified, in much the same way that the claim 'crossing the road is dangerous' can be justified. Crossing the road is dangerous, even to the experienced road user, if done carelessly. Likewise, using macros can be problematic. SECCODE quotes the classic i++ abuse of a macro call, and suggests that inline functions can eliminate this problem. This is certainly true where inline functions are available. It is true that C99 guarantees that inline functions are available, but nowhere is there any guarantee that a C99 implementation is available! Yes, within the terms of reference of SECCODE, the suggestion to use inline functions has obvious merit. But for those of us without access to inline functions, it is impractical. SECCODE itself recognises this, by pointing out portability concerns. For the experienced C programmer, the use of UPPER CASE for macro names is generally sufficient to act as a warning that macro arguments with side effects should be avoided. In the first code fragment, we see a #define that is clearly local to a function (because the fragment contains executable code). This is generally considered to be unwise. I can see why the fragment is written that way, of course - it's to save space! But in a document which purports to provide a guide to best practice, it's still a curious way to write code. The expansion given in the second code fragment is (trivially) incorrect. Strictly, it should be: int a = 81 / ((++i) * (++i) * (++i)); The SECCODE version of the expansion omits the extra parentheses that its previous definition requires. The third code fragment, which demonstrates the inline version of the code, is poorly written. When we're cubing a value, even a moderate input can result in overflow. For example, on 16-bit-int systems, i = 32 will produce overflow in the call to cube. On 32-bit-int systems, i = 1291 (hardly excessive) will produce overflow. Precisely how one would solve this problem depends on one's requirements. If it is known that excessive inputs will never occur, an assertion is appropriate. If they may well occur, it must be decided whether they constitute an error. If so, the function needs a way to report that error. Otherwise, an alternative strategy (e.g. bignums) must be considered. In any event, the function as written is insecure, because it can produce undefined behaviour. The fourth fragment illustrates that a clash between a macro parameter name and a file scope object name can cause incorrect results. It seems to me, however, that this is not so much a reason not to use macros as a reason not to use file scope objects! In the 'SWAP' example, the hoary old XOR trick is used to swap two values. This is a really bad idea, for two reasons: firstly, it only works on integer types: SWAP(mydoubleA, mydoubleB) will fail to compile. Secondly, if you do this: SWAP(myintA, myintA), you don't get a swap - you get 0! The example, then, is a poor one. Whilst the suggested replacement sidesteps the first problem neatly (because it suggests a function that takes int *, so nobody can reasonably expect it to swap doubles), it fails to address the second problem. Far better to use a temp: void swap(int *pa, int *pb) { int tmp = *pa; *pa = *pb; *pb = tmp; } This is guaranteed to work, provided only that pa and pb point to valid int objects. The example where the interaction of two macros and a file scope object produce incorrect results is rather contrived. It's an argument against using macros to adjust file scope object values. It's an argument against file scope object values themselves. It's an argument against tight coupling. But it's not an argument against macros. The claim that the execution of functions cannot be interleaved 'so problematic orderings are not possible' ignores the fact that the order of evaluation of multiple functions called in the same statement is not specified. Whilst this doesn't cause a problem in the example given, it can certainly cause problems in cases where the called functions have related side effects (e.g. updating the same object, writing to the same stream, or whatever). Although y = f(x) + g(x); is harmless in the example given, it is not a recipe for success. Lest the wrong impression be garnered from the above, let me reiterate that the danger of side effects being unwittingly duplicated by macros is significant, and the careful programmer should ensure that (a) macros don't evaluate arguments more than once if at all possible; (b) macro names are written in UPPER CASE to draw attention to them; (c) macros are only used if there is no sensible alternative that meets the project requirements. #end excerpt from clc I think what you are both saying about macros could be surmised in a paragraph. -- "I am waiting for them to prove that God is really American." ~~ Lawrence Ferlinghetti
Post Follow-up to this messageLouis Krupp wrote: > glen herrmannsfeldt wrote: <snip> > > I think you mean MIN instead of ABS. ABS would be something like: Oops. Make that MAX. Louis
Post Follow-up to this messageOn Mon, 31 Mar 2008 05:46:41 -0700 (PDT), Bamm <bammster@gmail.com> wrote: -|> For Fortran 77 define Floor as: -|> DINT(X)=X-DMOD(X,1.D0) -|> FLOOR(X)=DINT(X)-DMOD(2.D0+DSIGN(1.D0,X),3.D0) -| -|What is DMOD and DINT, and how are they different from MOD and INT? -|Thanks. These force Double Precision versions of MOD and AINT to be used. -| -|Btw, the problem has been solved. But I am looking at your suggestion -|as it might lead to something better.
Post Follow-up to this messageLouis Krupp wrote: > Louis Krupp wrote: > <snip> > > Oops. Make that MAX. > > Louis Apparently writing macro code is easy, naming them is the hard part? ;) ;) ;) Sorry, I can't resist temptation before my morning martini! Dick Hendrickson
Post Follow-up to this messagePowered by vBulletin
Copyright 2000-2006 Jelsoft Enterprises Limited.