Home     |     .Net Programming    |     cSharp Home    |     Sql Server Home    |     Javascript / Client Side Development     |     Ajax Programming

Ruby on Rails Development     |     Perl Programming     |     C Programming Language     |     C++ Programming     |     IT Jobs

Python Programming Language     |     Laptop Suggestions?    |     TCL Scripting     |     Fortran Programming     |     Scheme Programming Language


 
 
Cervo Technologies
The Right Source to Outsource

MS Dynamics CRM 3.0

Fortran Programming Language

"typedef" in F95/2003?


I have a program that I want to recompile to use different floating point
precisions.  A lot of compilers support a command-line option to switch
the default real type from single to double or quad, e.g.

Intel: -real_size 32,64,128
GNU Fortran: -fdefault-real-4,8
Portand Group: -r4,8,16
Sun F95: -xtypemap=real:32,64

so until now, I have been using the default real kind and compiler
switches.  However, the time has come to use some of DH Bailey and Yozo
Hida's work, which means substituting (for example) type(qd_real) for real
in the declarations.

If I'm going to go through the code to do this, what I would really like
to do is something like "typedef" in C, e.g. something like

typedef float my_real

for single precision

typedef double my_real

for double precision

typedef qd_real my_real

for quad-double precision.

All the declarations would use the "my_real" type instead of an explicit
type.

Can this sort of thing be done in Fortran 95/2003?

Thanks,

Chip

--
Charles M. "Chip" Coldwell
"Turn on, log in, tune out"

Chip Coldwell <coldw@frank.harvard.edu> wrote:
> I have a program that I want to recompile to use different floating point
> precisions.  A lot of compilers support a command-line option to switch
> the default real type from single to double or quad, e.g.

(I won't go into all the fine points of why I generally recommend
against using options like that.... since you are asking about moving
away from that method anyway.)

> If I'm going to go through the code to do this, what I would really like
> to do is something like "typedef" in C, e.g. something like

> typedef float my_real

> for single precision
...
> Can this sort of thing be done in Fortran 95/2003?

Not with that syntax, but yes. Are you aware of the kind type parameter
facility of f90? That was one of the major new features of f90. It sute
simplified my life a lot, as I used to spend lots of tiem converting
codes between single and double precision (in days when compilers didn't
tend to have have such switches at all).

You define a type parameter (which is an integer - some of us don't like
that, but that's the way it is). Best to do it in a module, such as

  module precisions
    integer, parameter :: my_real = ....an_appropriate value
  end module precision

There are several options for selecting the appropriate value. Often the
selected_real_kind intrinsic does just what you want. Or if you know
that you want single/double/quad, you can use something like kind(0.0)
or kind(0.0d0) or kind(non_portable_quad_literal). Or you can just
hard-wire the compiler dependent values. Hard-wiring does require
changing the code for different compilers, but it is only a single line
of code for the whole program.

Elsewhere in the program, do things like

  subroutine whatever
    use precisions
    real(my_real) :: x

Note that you do have to say real(my_real) instead of just my_real. Note
also that you can then use this kind parameter for other things such as
literal constants. For example 1.2345678_my_real is a literal constant
of the appropriate kind.

--
Richard Maine                    | Good judgement comes from experience;
email: last name at domain . net | experience comes from bad judgement.
domain: summertriangle           |  -- Mark Twain

Richard Maine wrote:

(snip on typedef and Fortran)

> Note that you do have to say real(my_real) instead of just my_real. Note
> also that you can then use this kind parameter for other things such as
> literal constants. For example 1.2345678_my_real is a literal constant
> of the appropriate kind.

The most common use for typedef in C is for structure types
where it avoids having to say struct in from of a structure type.

It seems, then, that having to say real() around a real kind is
somewhat the same as having to say struct in from of a struct type.
Most of the time it doesn't bother me to say struct, though.

Another solution is to use a preprocessor.

#define my_real real(my_real)

assuming it doesn't do recursive evaluation.

-- glen

On Wed, 23 May 2007, Richard Maine wrote:
> Not with that syntax, but yes. Are you aware of the kind type parameter
> facility of f90?

Yes, and that isn't going to work.  Suppose, for example, my compiler
supports (in addition to the command line switches) kind type parameters
4, 8 and 16 for real.  I.e.

real(kind=4) is single precision
real(kind=8) is double precision
real(kind=16) is quad precision

Now, what I want to do is use Yozo Hida's quad-double in place of reals --
that means that all of the variables that are reals in the single
precision version become structures in the quad-double version.  Because
of the operator overloading I can do the following

type(qd_real) :: x = qd_one
type(qd_real) :: y = qd_zero

if (x + y .eq. qd_one) then
   print *, "Yahoo, it works!"
end if

etc. etc.

The type(qd_real) is implemented as an array of four doubles wrapped by a
structure.  Actually, it's implemented in C++, but they provide a Fortran
interface.

For your suggestion to work, I would have to be able to define a *new*
type kind parameter for real that the compiler isn't aware of already.  I
don't think that can be done.

Chip

--
Charles M. "Chip" Coldwell
"Turn on, log in, tune out"

Ah. I see. I didn't recognize that as what you were asking for. Yes,
that would be useful. In fact, I was once agitating in favor of a
typealias facility in f2003 for exactly that reason - so that I could
use an intrinsic type where available and a derived type substitute
otherwise. Typealias (that's what it was called) was actually in the
f2003 draft until pretty late in the process. It got pulled for various
reasons. I forget all the details, but I do recall it being pointed out
to me that it would not actually have achieved this functionality in
practice. Yes, you could declare variables and have defined operators.
But there are too many other parts of the language where things would
fall apart.

Probably the simplest one is literal constants. But there were also a
bunch of others. I don't recall all the details (except fot the literal
constant thing), but I do recall being convinced that the typealias
facility didn't really work for that problem. Perhaps a more complicated
facility might have, but the "simple" one that was in the f2003 draft
wasn't coming close.

--
Richard Maine                    | Good judgement comes from experience;
email: last name at domain . net | experience comes from bad judgement.
domain: summertriangle           |  -- Mark Twain

On Wed, 23 May 2007, Richard Maine wrote:
> Yes, you could declare variables and have defined operators.
> But there are too many other parts of the language where things would
> fall apart.

> Probably the simplest one is literal constants.

I don't get it.  What falls apart with literal constants as a result of
introducing typedef/typealias into the language?

Chip

--
Charles M. "Chip" Coldwell
"Turn on, log in, tune out"

Chip Coldwell <coldw@frank.harvard.edu> wrote:
> On Wed, 23 May 2007, Richard Maine wrote:

> > Yes, you could declare variables and have defined operators.
> > But there are too many other parts of the language where things would
> > fall apart.

> > Probably the simplest one is literal constants.

> I don't get it.  What falls apart with literal constants as a result of
> introducing typedef/typealias into the language?

How do you write one of these quad precision literal constants? Answer:
you don't - not in any way that automatically converts with the typedef.
They are structure constructors instead.

--
Richard Maine                    | Good judgement comes from experience;
email: last name at domain . net | experience comes from bad judgement.
domain: summertriangle           |  -- Mark Twain

I'm still confused.  I'm not aware of any requirement that every derived
type must be representable as a literal constant, if that's what you
meant.

If you mean literal constants as intializers of a derived type that has
been typedef'd/typealias'd, then the problem is solved in C++ by requiring
a constructor that takes a single formal parameter of the same time as the
literal constant -- so if you had

typedef class qd_real my_real;

and the qd_real class contained a constructor that takes a single floating
point argument then you could write:

my_real foo(void)
{
        my_real one = 1.0;
        my_real two = 2.0;
        return one + two;

}

and it does what you want.  Plus, I can go back later and alter the one
line to read

typedef double my_real;

and it still does what I want after a recompile.

You can get nearly the same result by defining assignment operators in
Fortran 95, and in fact that is what qd does, except that I can't use the
type alias.  I can write

function foo
  type(qd_real) :: foo
  type(qd_real) :: one = 1.0
  type(qd_real) :: two = 2.0

  foo = 1.0 + 2.0
end function foo

But if I want to switch between native data types and derived data types,
I have to re-write that function or use a preprocessor as was suggested
earlier.

Chip

--
Charles M. "Chip" Coldwell
"Turn on, log in, tune out"

In article <1hyk8on.1ihaepv2jq7c4N%nos@see.signature>,

Richard Maine <nos@see.signature> wrote:
>Chip Coldwell <coldw@frank.harvard.edu> wrote:

>> I have a program that I want to recompile to use different floating point
>> precisions.

>There are several options for selecting the appropriate value. Often the
>selected_real_kind intrinsic does just what you want.

I don't know if this will help Chip, but if you use some compilers that
offer quad precision and some that don't, (a situation I'm in from time
to time), the following cunning ploy, which I saw here some time ago,
will make a REAL(hp) variable higher precision than double if that's
available, but double precision if not.

INTEGER, PARAMETER :: dp = kind(1d0), &
     qp = selected_real_kind(precision(1d0)+2), &
     hp = (dp*(1-sign(1,qp))+qp*(1+sign(1,qp)))/2

-- John Harper, School of Mathematics, Statistics and Computer Science,
Victoria University, PO Box 600, Wellington 6140, New Zealand
e-mail john.har@vuw.ac.nz phone (+64)(4)463 5341 fax (+64)(4)463 5045

On Wed, 24 May 2007, John Harper wrote:

> I don't know if this will help Chip, but if you use some compilers that
> offer quad precision and some that don't, (a situation I'm in from time
> to time), the following cunning ploy, which I saw here some time ago,
> will make a REAL(hp) variable higher precision than double if that's
> available, but double precision if not.

> INTEGER, PARAMETER :: dp = kind(1d0), &
>      qp = selected_real_kind(precision(1d0)+2), &
>      hp = (dp*(1-sign(1,qp))+qp*(1+sign(1,qp)))/2

That's a cute trick, but not really what I'm looking for.  My original
post was pretty obfuscated by the discussion of default real kinds, etc.  
What I really want to be able to do is declare variables that are of type
my_real, where during one compile my_real is a native real(kind=something)
type and during a subsequent recompile my_real is a derived data type
(from Hida/Bailey's package).

Chip

--
Charles M. "Chip" Coldwell
"Turn on, log in, tune out"

No. I mean that you can't take the same source code, change just the
typealias/typedef/whatever, and have the code continue to work. Sure,
there are some very limitted cases where you can do that, but the
limitations turn out to be too strong to be useful. In practice, you
wouldn't be able to do it for most useful codes.

> You can get nearly the same result by defining assignment operators in
> Fortran 95,

No, you can't. Literal constants appear in other contexts than as the
sole thing on the RHS of an assignment. If you do

  foo = 1.23

then the 1.23 is a single precision constant. Nothing you can do with a
defined assignment will change that. If foo is a double or a quad,
you'll have just lost precision. And if you do

  call sub(1.23)

then assignment doesn't have anything to do with the question. If the
dummy argument is anything other than a single real, then it won't work
at all.

For another example, your

> function foo
>   type(qd_real) :: foo
>   type(qd_real) :: one = 1.0
>   type(qd_real) :: two = 2.0

Is invalid because initializers don't use defined assignment, even if
you have such a thing. If they did use defined assignment, you'd still
have the precision problem with most values; 1.0 and 2.0 are not
particularly difficult cases that stretch the limits.

You are just talking about ways to avoid using quad literal copnstants.
That's not the same thing as defining how to write them.

Yes, you could probably restrict yourself to writing code that would
work. You'd have to be very restrictive - more so than the above
example, which as I noted won't work.

It was judged that, on the whole, this would work so poorly for this
purpose that it would be a disservice to claim that the typealias
feature addressed this problem, when most users would find that it
wouldn't work for them in practice. If you disagree with that judgement,
so be it.

--
Richard Maine                    | Good judgement comes from experience;
email: last name at domain . net | experience comes from bad judgement.
domain: summertriangle           |  -- Mark Twain

On Wed, 23 May 2007, Richard Maine wrote:
> Chip Coldwell <coldw@frank.harvard.edu> wrote:

> > You can get nearly the same result by defining assignment operators in
> > Fortran 95,

> No, you can't. Literal constants appear in other contexts than as the
> sole thing on the RHS of an assignment. If you do

>   foo = 1.23

> then the 1.23 is a single precision constant.

Right, and "foo" is whatever I've declared it to be.  In the case of the
quad double types from the Hida/Bailey package, there exists a defined
assignment operator for this combination.

> Nothing you can do with a defined assignment will change that. If foo is
> a double or a quad, you'll have just lost precision.

How do you figure that?  If I put a single precision value (the literal
constant) into a quad double variable, I've gained precision, right?

> And if you do

>   call sub(1.23)

> then assignment doesn't have anything to do with the question. If the
> dummy argument is anything other than a single real, then it won't work
> at all.

Right, but it could.  In C++, if "sub" were declared with a quad double
dummy argument, the compiler would generate a temporary quad double
variable, assign the single precision value 1.23 to it using the defined
assignment operator, and then pass the temporary to the called function.  
Clearly that's not possible unless "sub" has an explicit interface, so
perhaps it's ruled out for Fortran on that basis.

> For another example, your

> > function foo
> >   type(qd_real) :: foo
> >   type(qd_real) :: one = 1.0
> >   type(qd_real) :: two = 2.0

> Is invalid because initializers don't use defined assignment, even if
> you have such a thing.

Fair enough.  Bad example.

> You are just talking about ways to avoid using quad literal copnstants.
> That's not the same thing as defining how to write them.

In practice, the authors of the library solved this problem by providing
functions for assignment to quad double variables from character strings.  
So put your literal in quotes if you need the full precision to represent
its value.

However, that is not my point; in fact, this whole discussion has wandered
off into the weeds.

I'm not worried about precision, or the loss thereof.  I'm not arguing
about whether or not you need to be able to represent literal constants of
an arbitrary derived type.  What I am trying to understand is why
introducing "typealias" into the language makes coping with literal
constants more difficult for the compiler writer.  Maybe I'm a little
thick about this, but I just don't understand your explanation.

> It was judged that, on the whole, this would work so poorly for this
> purpose that it would be a disservice to claim that the typealias
> feature addressed this problem, when most users would find that it
> wouldn't work for them in practice. If you disagree with that judgement,
> so be it.

I don't agree or disagree.  I simply don't understand the basis for that
judgement.

Chip

--
Charles M. "Chip" Coldwell
"Turn on, log in, tune out"

Yes.  But:

     my_real one = 1.0/3.0

does not do what you want.  Nor, for that matter, does

     my_real one = 0.1

In both cases, because your literal is of default real type rather than
the typedef'ed type, you get degraded precision.

Even between just single and double precision, this seems to turn up as
a bug in someone's code here about once every other month, at least.

- Brooks

--
The "bmoses-nospam" address is valid; no unmunging needed.

Chip Coldwell <coldw@frank.harvard.edu> wrote:
> On Wed, 23 May 2007, Richard Maine wrote:
> >   foo = 1.23
> > If foo is a double or a quad, you'll have just lost precision.

> How do you figure that?  If I put a single precision value (the literal
> constant) into a quad double variable, I've gained precision, right?

No! No! No! 100 times no. This is a fundamental error regularly made by
new users and corrected here. Precision, like virginity, is never
regained once lost. (Though it isn't that good an analogy, as precision
isn't such an all-or-nothing thing). You have converted it to a quad
precision representation, but that does *NOT* get you a value accurate
to quad precision; i.e. it does not have that precision - just that
representation. This is *NOT* the same thing.

> > And if you do

> >   call sub(1.23)

> > then assignment doesn't have anything to do with the question.

> Right, but it could.  In C++,...

No, it can't. This is Fortran - not C++. If you want to redo the entire
language from ground up, then that's another matter. You'll also break
existing codes in the process. That doesn't fit well in Fortran.

And even if it did, you are just illustrating the point - that just
defining a typealias/typedef is not a simple method of providing the
functionality in question. You are proposing redefining other language
fundamentals that have implications all over the place. Suddenly
typealias isn't such a simple addition any more. I wouldn't claim that
it is impossible to make something like typealias work. If I mistakenly
impled that, I didn't mean to. However, making it work well for that
functionality is not at all simple. If you expect that functionality out
of it, then you have to at the very least do huge amounts of work
elsewhere in the language.

That wasn't going to happen at the time. No way. That wasn't even
suggested. This came up quite late in the f2003 process. I think it was
in the public review of the FCD. The question at hand was whether to
leave it in as is or take it out.

> if "sub" were declared with a quad double
> dummy argument, the compiler would generate a temporary quad double
> variable, assign the single precision value 1.23 to it using the defined
> assignment operator, and then pass the temporary to the called function.
> Clearly that's not possible unless "sub" has an explicit interface, so
> perhaps it's ruled out for Fortran on that basis.

No, that's not the only basis. Argument passing has implications all
over the place. For example, you just broke generic resolution - rather
badly, I might add - if actual arguments are compatible with any dummy
that there is an appropriate assignment for. (Sounds more like PL/I).
You've also either done funny things to arguments that aren't intent(in)
or you have made the rules for intent(in) argument agreement different
from all others.

> What I am trying to understand is why
> introducing "typealias" into the language makes coping with literal
> constants more difficult for the compiler writer.

It doesn't. So that's why you keep having trouble understanding why it
does. Difficulty of implementation is not the only criteria for adding
things to the language. I don't recall it being particularly a point at
all for this feature. Heck, you probably can sort of do it as a user
right now without bothering the compiler writers. Just use your favorite
macro processor as a preprocessor for your code. The result you'll get
is not a lot different from what the proposed typealias feature was.

The judgement was that the feature did not achieve the stated goal of
making it practical to write code that could easily be converted between
intrinsic and derived types. I said nothing at all about implementation
difficulty.

There were also other issues with typealias, but they were unrelated to
this. (And I'm quite tired enough of this discussion that I'm not going
to wander off into them, but it was argued that typalias as proposed
wasn't going to do those jobs well either). In fact, this wasn't even
the main reason typealias was proposed. I've just been concentrating on
why this use of type alias didn't provide a basis for keeping it.

--
Richard Maine                    | Good judgement comes from experience;
email: last name at domain . net | experience comes from bad judgement.
domain: summertriangle           |  -- Mark Twain

The literal "1.23" is equal to the exact value 1.23 plus some error,
with that error being on the order of half the precision of a
single-precision real variable.

Your "foo" variable, on the other hand, as a quad-double, would normally
expected to have a maximum numerical error that is substantially smaller
than the error in a single-precision real variable.

By assigning the literal "1.23" to your quad-double variable, you obtain
a result that has substantially larger error (i.e., substantially less
precision) than would be expected for a variable of its type.  This
error propagates through all of the calculations that are done with this
variable, and to a rough approximation this will cause a comparable
level of error in the final results.

Thus, you have "lost precision" in your calculations, compared to what
would have happened had you used a literal of the "correct" precision.

(Or, conversely, if you look at it from the perspective of what happens
if you change the type of "foo" -- you might be expecting to gain
precision, but you haven't actually gained any; the error in foo
compared to an exact 123/100 is the same as it was when foo was
single-precision.)

- Brooks

--
The "bmoses-nospam" address is valid; no unmunging needed.

Chip Coldwell wrote:
> I'm not worried about precision, or the loss thereof.  I'm not arguing
> about whether or not you need to be able to represent literal constants of
> an arbitrary derived type.  What I am trying to understand is why
> introducing "typealias" into the language makes coping with literal
> constants more difficult for the compiler writer.  Maybe I'm a little
> thick about this, but I just don't understand your explanation.

Richard's point is that, if one cannot type-alias literal constants
(that is, one cannot write "1.23" in a way that it is equal to the
closest representation of 123/100 for some type-aliased type, without
the programmer knowing what the type is aliased to), then being able to
type-alias variables does not produce the benefits that he was
introducing the feature in order to provide.

- Brooks

--
The "bmoses-nospam" address is valid; no unmunging needed.

> That's a cute trick, but not really what I'm looking for.  My original
> post was pretty obfuscated by the discussion of default real kinds, etc.  
> What I really want to be able to do is declare variables that are of type
> my_real, where during one compile my_real is a native real(kind=something)
> type and during a subsequent recompile my_real is a derived data type
> (from Hida/Bailey's package).

The only way out that I see is to use always use a derived type, even in the
case where an intrinsic type would suffice. With an optimizing compiler, the
resulting code shouldn't be too different with regard to performance - it's
just somewhat more verbose (e.g., structure constructors instead of literals).

        Jan

On 2007-05-24, Richard Maine <nos@see.signature> wrote:

> No! No! No! 100 times no. This is a fundamental error regularly made by
> new users and corrected here. Precision, like virginity, is never
> regained once lost.

Hmm... that last sentence really seems like a nice quote to use
as a signature in my emails or on UseNet... tnx a lot Richard! ;-)

Bart

--
"Precision, like virginity, is never regained once lost."
        -- Richard Maine --

>>No! No! No! 100 times no. This is a fundamental error regularly made by
>>new users and corrected here. Precision, like virginity, is never
>>regained once lost.
> Hmm... that last sentence really seems like a nice quote to use
> as a signature in my emails or on UseNet... tnx a lot Richard! ;-)

Indeed.

Of course, this goes back at least to Ludwig Boltzmann and the concept of
increasing entropy, which translates to irreversible computation in this
particular case.

        Jan

On Thu, 24 May 2007, [ISO-8859-1] Jan Vorbrggen wrote:
> > That's a cute trick, but not really what I'm looking for.  My original post
> > was pretty obfuscated by the discussion of default real kinds, etc.  What I
> > really want to be able to do is declare variables that are of type my_real,
> > where during one compile my_real is a native real(kind=something) type and
> > during a subsequent recompile my_real is a derived data type (from
> > Hida/Bailey's package).

> The only way out that I see is to use always use a derived type, even in the
> case where an intrinsic type would suffice. With an optimizing compiler, the
> resulting code shouldn't be too different with regard to performance - it's
> just somewhat more verbose (e.g., structure constructors instead of literals).

Actually, there is another solution, but it's pretty fugly: use implicit
typing.

IMPICIT TYPE(qd_real) (Q)

Chip

--
Charles M. "Chip" Coldwell
"Turn on, log in, tune out"

On Thu, 24 May 2007, Bart Vandewoestyne wrote:
> On 2007-05-24, Richard Maine <nos@see.signature> wrote:

> > No! No! No! 100 times no. This is a fundamental error regularly made by
> > new users and corrected here. Precision, like virginity, is never
> > regained once lost.

> Hmm... that last sentence really seems like a nice quote to use
> as a signature in my emails or on UseNet... tnx a lot Richard! ;-)

Indeed, props to Richard for a nice turn of phrase.  However, at the risk
of being overly pedantic, let me point out that in this code:

real(kind=16) :: foo

foo = 1.23

no precision is *lost* in the assignment.  The programmer may believe that
he has a quad precision value called "foo" when he really has the single
precision value, but he never had more than the single precision value to
start with in the literal constant, hence nothing was lost.  Yes, it is a
trap for the unwary and I can believe that code like this generates lots
of traffic for this newsgroup.

Digging deeper into pedantry, let me point out that in this code:

foo = 0.5

the value of "foo" *is* the quad precision value, not the single precision
value.  In fact, any integer power of 0.5 and any number exactly
expressible as a sum of integer powers of 0.5 will not suffer when it's
type is promoted:

foo = 0.656

similarly is stored exactly with quad precision in the variable foo.  
This assumes a binary radix for floating point.  IBM just announced a
POWER6 CPU that can do decimal floating point, which means in principle
one could write a compiler such that any single precision decimal literal
constant would be stored as an exact value in a quad precision variable.  
Not directly relevant, but kinda interesting.

Before somebody jumps on me, yes, I know this does not generalize and that
when doing error analysis you must propagate the single precision errors
through the quad precision variables even if the single precision value
is the exact value of a binary floating point number.

Chip

--
Charles M. "Chip" Coldwell
"Turn on, log in, tune out"

Chip Coldwell <coldw@frank.harvard.edu> wrote:
> However, at the risk
> of being overly pedantic, let me point out that in this code:

> real(kind=16) :: foo

> foo = 1.23

> no precision is *lost* in the assignment.

I quite agree. The precision is not lost in the assignment. The
precision is lost in writing 1.23 instead of 1.23_16. That's why we got
on the subject of literal constant syntax. It is the lack of a suitable
lteral constant syntax for typealias that causes problems. I think that
a comment was once made in teh discussion in J3 (might have even been
made by me after I understood the problem - I forget) that typealias
doesn't do a good enough job of hiding the underlying definition of the
type; you still have to treat it like an intrinsic or derived type,
depending which the underlying type is.

--
Richard Maine                    | Good judgement comes from experience;
email: last name at domain . net | experience comes from bad judgement.
domain: summertriangle           |  -- Mark Twain

On 24 May, 16:20, Chip Coldwell <coldw@frank.harvard.edu> wrote:

Here is a simple program

program ex02
implicit none
integer , parameter :: long=selected_real_kind(15,307)

real        :: a,b,c
real (long) :: la,lb,lc

  a=1.23
  b=0.5
  c=0.656

  print *,a
  print *,b
  print *,c

  la=1.23
  lb=0.5
  lc=0.656

  print *,la
  print *,lb
  print *,lc

  la=1.23_long
  lb=0.5_long
  lc=0.656_long

  print *,la
  print *,lb
  print *,lc

end program ex02

here is the output from 3 compilers
(Nag, Intel and Lahey)

   1.2300000
   0.5000000
   0.6560000
   1.2300000190734863
   0.5000000000000000
   0.6560000181198120
   1.2300000000000000
   0.5000000000000000
   0.6560000000000000

   1.230000
  0.5000000
  0.6560000
   1.23000001907349
  0.500000000000000
  0.656000018119812
   1.23000000000000
  0.500000000000000
  0.656000000000000

1.23000002
0.500000000
0.656000018
1.230000019073486
0.5000000000000000
0.6560000181198120
1.230000000000000
0.5000000000000000
0.6560000000000000

see richards subseqent post for more information.

Ian Chivers

On Thu, 24 May 2007 ian_d_chiv@yahoo.co.uk wrote:

> Here is a simple program

Well, I went and gave you a bad example again.  I meant for

0.656 = 0.5 + 0.125 + 0.031

that last value was supposed to be 1.0/32.0, but it isn't.  Please repeat
your experiment with

0.65625

instead.

Chip

--
Charles M. "Chip" Coldwell
"Turn on, log in, tune out"

Chip Coldwell wrote:
> On Thu, 24 May 2007 ian_d_chiv@yahoo.co.uk wrote:
>> Here is a simple program

> Well, I went and gave you a bad example again.  I meant for

> 0.656 = 0.5 + 0.125 + 0.031

> that last value was supposed to be 1.0/32.0, but it isn't.  Please repeat
> your experiment with

> 0.65625

Actually, your original example -- and Ian's subsequent test program -- is the good
example; and the one above using 0.65625 and 0.03125 is the special case.

Are you expecting to always do floating point arithmetic with reals that just happen to be
exactly representable in base-2? That would be nice. I don't get to pick the numbers I
work with so the difference between representation and precision is important. :o)

cheers,

paulv

--
Paul van Delst             Ride lots.
CIMSS @ NOAA/NCEP/EMC               Eddy Merckx

Add to del.icio.us | Digg this | Stumble it | Powered by Megasolutions Inc