From: Arjen Markus on
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
"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
"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

"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
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