From: Arjen Markus on 7 Jan 2010 08:53 On 7 jan, 14:45, glen herrmannsfeldt <g...(a)ugcs.caltech.edu> wrote: > Arjen Markus <arjen.markus...(a)gmail.com> wrote: > > (snip) > > > However, a formula like: > > t = 0.1 + tan(phi) > > will result in a loss of precision, if t and phi are double > > precision. 0.1 is still a single-precision literal and that > > gets promoted to double precision with the addition. > > http://en.wikipedia.org/wiki/Accuracy_and_precision > > I would say that the pricision is fine, but the accuracy is not. > The multiplication will be done in double precision with a value > that is not as close to 0.1d0 as it should be. (Assuming binary > hardware.) Small changes in tan(phi) will result in appropriate > small changes in t (precision), but likely the wrong value for t. > > > So in that case: > > t = 0.d0 + tan(phi) > > is the correct way to proceed. > > Probably better to avoid literals and use parameters instead. Then > > the precision can be controlled in one place. > > For the example given, the accuracy is even worse than for 0.1 > due to a typographic error. 0.d0 is not better than 0.1e0 in > this case. > > -- glen No, you are quite right :). I wanted an example with non-integer values ... and there I go! Regards, Arjen
From: robin on 7 Jan 2010 10:06 "ralf.schaa" <ralf.schaa(a)gmail.com> wrote in message news:4c3ee892-b369-4895-9992-54be82715d40(a)r24g2000yqd.googlegroups.com... | probably a faq, but here goes... | i would like to write lengthy formulae without the *.0d0 (or other | specified kind types) and use, where possible, the integer, for | example: | | real( double ) :: t, phi | t = 5+tan(phi) | | I think this should not result in a precision loss, is it? | | What about division? | | t = 5+tan(phi) / 3 ? With whole number values, there is no precision loss. However, you need to be careful to ensure that integer arithmetic is avoided. What you need to worry about is values containing fractions, especially things like 0.1 whucg need D0 appended if you are using double precision (and other appendage for other extended precisions).
From: robin on 7 Jan 2010 10:07 "glen herrmannsfeldt" <gah(a)ugcs.caltech.edu> wrote in message news:hi3dse$ooi$1(a)naig.caltech.edu... | ralf.schaa <ralf.schaa(a)gmail.com> wrote: | > probably a faq, but here goes... | > i would like to write lengthy formulae without the *.0d0 (or other | > specified kind types) and use, where possible, the integer, for | > example: | | > real( double ) :: t, phi | > t = 5+tan(phi) | | > I think this should not result in a precision loss, is it? | | For add, subtract, multiply and divide if the other operand is an | appropriate REAL kind then an integer will be converted to the | same kind before the operation. There should be no loss. | In days past there were suggestions that some might do the conversion | at run time, but that should not be a problem for any current compiler. | | > What about division? | | If both arguments are integers then integer division will be done. | Otherwise it should be fine. | | > t = 5+tan(phi) / 3 ? | | For powers, you normally want an integer for the power if it | is actually integer. That is, use x**3 instead of x**3.0D0. Especially important if x is negative.
From: robin on 7 Jan 2010 10:08 "Arjen Markus" <arjen.markus895(a)gmail.com> wrote in message news:25094058-7774-4245-ba19-8ad40785bb11(a)m3g2000yqf.googlegroups.com... | On 7 jan, 01:39, "ralf.schaa" <ralf.sc...(a)gmail.com> wrote: | > probably a faq, but here goes... | > i would like to write lengthy formulae without the *.0d0 (or other | > specified kind types) and use, where possible, the integer, for | > example: | > | > real( double ) :: t, phi | > t = 5+tan(phi) | > | > I think this should not result in a precision loss, is it? | > | > What about division? | > | > t = 5+tan(phi) / 3 ? | > | > Cheers | > -Ralf | | However, a formula like: | | t = 0.1 + tan(phi) | | will result in a loss of precision, if t and phi are double precision. | 0.1 is still a single-precision literal and that gets promoted to | double precision with the addition. | | So in that case: | | t = 0.d0 + tan(phi) um, 0.1D0 | is the correct way to proceed.
From: Richard Maine on 7 Jan 2010 11:52 Arjen Markus <arjen.markus895(a)gmail.com> wrote: > However, a formula like: > > t = 0.1 + tan(phi) > > will result in a loss of precision, if t and phi are double precision. > 0.1 is still a single-precision literal and that gets promoted to > double precision with the addition. That's a good specific example, and one of the more common kinds of problems. I also think it well illustrates what I consider to be the most important issue in this area. In particular, One should learn the rules (they aren't horribly complicated) and pay deliberate attention to the type and kind of everything. It is ok (in my estimation) to use some of those rules to make a formula look (and thus read) a little simpler. I've been known to use things like 2*some_real_expression myself. But it is not ok to shortcut the thinking part. One should understand what rule allows each notational shortcut that you might make. If you get in the habit of making notational shortcuts without thinking about them, eventually you will screw up - pretty much guaranteed. The major rules of interest (very informally stated) are 1. Watch out for literal constants, as above. They are not converted (at least per the standard) until what I'd just summarize as too late. Thus only shorten literal constants in cases where they are exact. Mostly, that means integer values. Shortening 3.0d0 to 3 may be ok, depending on the other rules. Shortening 0.3d0 or 0.3 is not. Some compilers might "help" you by figuring out what you probably meant in some cases. I personally regard that "help" as a negative that just hides the problem. 2. Type and kind promotion happens only operation by operation. The "lowest" type/kind in a particular operation is promoted to the highest. You can *NOT* just look for the highest type/kind in the whole expression and assume that will apply everywhere. For example, in double+single/3, the single/3 operation will be done in single precision because that is the highest type/kind of its operands. The fact that there is a double close by in the expression is irrelevant. The addition will be done in double precision, but the division will not be (at least per the standard). Likewise in double+tan(2.0), the tan function is the single precision version, and, as noted elsewhere tan(2) is just nonstandard (unless you have extended the tan generic yourself). 3. Exponentiation is a special case. real**integer is not promoted (and you don't want it to be). 4. Particularly watch out for integer division. 1/3 is 0. This isn't actually a special rule. It is more a consequence of rule 2 above. It just happens to be a particularly egregious example. -- Richard Maine | Good judgment comes from experience; email: last name at domain . net | experience comes from bad judgment. domain: summertriangle | -- Mark Twain
First
|
Prev
|
Next
|
Last
Pages: 1 2 3 Prev: Decline in posting counts Next: To print or not to print |