Converting character to float.

  • Follow


I am learning fortran by writing a series of short programs and have
met with some success! I am having a few problems with the one that
reads data from a text file and keeps a running total of a cost. The
CSV file contains the following:

fuel,SMITH,55.99
accomodation,SMITH,28.50
food,SMITH,12.99
food,JONES,18.50
books,JONES,5.99
accomodation,SMITH,55.68
books,SMITH,24.98

My Fortran program looks like this:

      ! a simple fortran program to read a csv file
      ! containing expenses data, print off each cost
      ! and keep a running total
      program fileread
      	character*16 a
      	character*16 b
      	character*16 c
      	open(unit=1, file='expenses.txt')
      	do while(.true.)
      		read (1,*,end=99) a, b, c
      		print *,c
      	enddo
99      continue
      end program fileread

The next step is to create a float variable called total and use it to
keep a running total of the costs. The problem is how to I convert
each of the expense values into a float so I can add them up.

Can anyone help?

cheers
0
Reply marktyers (16) 9/14/2010 7:57:37 PM

On 2010-09-14 16:57:37 -0300, marktyers <marktyers@gmail.com> said:

> I am learning fortran by writing a series of short programs and have
> met with some success! I am having a few problems with the one that
> reads data from a text file and keeps a running total of a cost. The
> CSV file contains the following:
> 
> fuel,SMITH,55.99
> accomodation,SMITH,28.50
> food,SMITH,12.99
> food,JONES,18.50
> books,JONES,5.99
> accomodation,SMITH,55.68
> books,SMITH,24.98
> 
> My Fortran program looks like this:
> 
>       ! a simple fortran program to read a csv file
>       ! containing expenses data, print off each cost
>       ! and keep a running total
>       program fileread
>       	character*16 a
>       	character*16 b
>       	character*16 c

           real c

>       	open(unit=1, file='expenses.txt')
>       	do while(.true.)
>       		read (1,*,end=99) a, b, c
>       		print *,c
>       	enddo
> 99      continue
>       end program fileread
> 
> The next step is to create a float variable called total and use it to
> keep a running total of the costs. The problem is how to I convert
> each of the expense values into a float so I can add them up.
> 
> Can anyone help?
> 
> cheers

Since the third field is already a nice floating point (default real in Fortran
terminology) just declare "c" as real and you are done. The system will do
the heavy lifting for you.

If there is ever a problem with the data not being nice, etc, then you will
have to do the heavy lifting! :-(


0
Reply Gordon.Sande1 (250) 9/14/2010 8:21:28 PM


marktyers <marktyers@gmail.com> wrote:

> I am learning fortran by writing a series of short programs and have
> met with some success! I am having a few problems with the one that
> reads data from a text file and keeps a running total of a cost. The
> CSV file contains the following:
> 
> fuel,SMITH,55.99
> accomodation,SMITH,28.50
> food,SMITH,12.99
> food,JONES,18.50
> books,JONES,5.99
> accomodation,SMITH,55.68
> books,SMITH,24.98
> 
> My Fortran program looks like this:
> 
>       ! a simple fortran program to read a csv file
>       ! containing expenses data, print off each cost
>       ! and keep a running total
>       program fileread
>               character*16 a
>               character*16 b
>               character*16 c
>               open(unit=1, file='expenses.txt')
>               do while(.true.)
>                       read (1,*,end=99) a, b, c
>                       print *,c
>               enddo
> 99      continue
>       end program fileread
> 
> The next step is to create a float variable called total and use it to
> keep a running total of the costs. The problem is how to I convert
> each of the expense values into a float so I can add them up.
> 
> Can anyone help?

Well, it would seem easier to just have c be a real in the first place.
I just took your above code and file as is, changing nothing except for
the declaration of c, and it worked fine.

If there is some particular other reason why you want c to be character
(which there might be), then what you want is called an internal read.
An internal read looks just like a "normal" (external file) read except
that you are reading from a character variable instead of from a file.
For example

   read(c,*) x

would do the trick in your case, where x is a real variable.

While trying out this code (to make sure I was telling the truth when I
said that it worked with just the declaration change), I did notice two
small things that I'll comment on.

1. Using single-digit unit numbers is generally inadvisable. They often
have special uses that canconflict with your use. The most common
special-use unit numbers are 5 and 6, but the details do vary among
compilers. It is best to just avoid single digit ones at all. It is
unfortunate that the language makes you have to choose a numeric
identifier for a unit, and then places these pitfalls in the way of your
choice, but that's historical (or, as they sometomes say, hysterical).

2. "do while(.true.)" is a strange pseudo-Pascalism that has worked its
way into some people's Fortran style, possibly because there was a time
when "DO while" was a common Fortran extension, but the unadorned DO was
not. It is more simply spelled as just plain

  DO

Nothing more. The while(.true.) part is not needed.

-- 
Richard Maine                    | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle           |  -- Mark Twain
0
Reply nospam47 (9742) 9/14/2010 8:34:23 PM

On Sep 14, 9:34=A0pm, nos...@see.signature (Richard Maine) wrote:
> marktyers <markty...@gmail.com> wrote:
> > I am learning fortran by writing a series of short programs and have
> > met with some success! I am having a few problems with the one that
> > reads data from a text file and keeps a running total of a cost. The
> > CSV file contains the following:
>
> > fuel,SMITH,55.99
> > accomodation,SMITH,28.50
> > food,SMITH,12.99
> > food,JONES,18.50
> > books,JONES,5.99
> > accomodation,SMITH,55.68
> > books,SMITH,24.98
>
> > My Fortran program looks like this:
>
> > =A0 =A0 =A0 ! a simple fortran program to read a csv file
> > =A0 =A0 =A0 ! containing expenses data, print off each cost
> > =A0 =A0 =A0 ! and keep a running total
> > =A0 =A0 =A0 program fileread
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 character*16 a
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 character*16 b
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 character*16 c
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 open(unit=3D1, file=3D'expenses.txt')
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 do while(.true.)
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 read (1,*,end=3D99) a, b, c
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 print *,c
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 enddo
> > 99 =A0 =A0 =A0continue
> > =A0 =A0 =A0 end program fileread
>
> > The next step is to create a float variable called total and use it to
> > keep a running total of the costs. The problem is how to I convert
> > each of the expense values into a float so I can add them up.
>
> > Can anyone help?
>
> Well, it would seem easier to just have c be a real in the first place.
> I just took your above code and file as is, changing nothing except for
> the declaration of c, and it worked fine.
>
> If there is some particular other reason why you want c to be character
> (which there might be), then what you want is called an internal read.
> An internal read looks just like a "normal" (external file) read except
> that you are reading from a character variable instead of from a file.
> For example
>
> =A0 =A0read(c,*) x
>
> would do the trick in your case, where x is a real variable.
>
> While trying out this code (to make sure I was telling the truth when I
> said that it worked with just the declaration change), I did notice two
> small things that I'll comment on.
>
> 1. Using single-digit unit numbers is generally inadvisable. They often
> have special uses that canconflict with your use. The most common
> special-use unit numbers are 5 and 6, but the details do vary among
> compilers. It is best to just avoid single digit ones at all. It is
> unfortunate that the language makes you have to choose a numeric
> identifier for a unit, and then places these pitfalls in the way of your
> choice, but that's historical (or, as they sometomes say, hysterical).
>
> 2. "do while(.true.)" is a strange pseudo-Pascalism that has worked its
> way into some people's Fortran style, possibly because there was a time
> when "DO while" was a common Fortran extension, but the unadorned DO was
> not. It is more simply spelled as just plain
>
> =A0 DO
>
> Nothing more. The while(.true.) part is not needed.
>
> --
> Richard Maine =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0| Good judgment come=
s from experience;
> email: last name at domain . net | experience comes from bad judgment.
> domain: summertriangle =A0 =A0 =A0 =A0 =A0 | =A0-- Mark Twain

Thanks for both the replies. I have tweaked my program thus:

      ! a simple fortran program to read a csv file
      ! containing expenses data, print off each cost
      ! and keep a running total
      program fileread
      	character*16 a
      	character*16 b
      	real c
      	real cost
      	real total =3D 0.0
      	open(unit=3D10, file=3D'expenses.txt')
      	do
      		read (10,*,end=3D99) a, b, c
      		print *,c
      	enddo
99      continue
      end program fileread

and it works!

However I have a follow-up question. How can I round up the reals to 2
decimal places? At the moment they are accurate to 7 which causes a
few wobbles:

   55.990002
   28.500000
   12.990000
   18.500000
   5.9899998
   55.680000
   24.980000

thanks
Mark
0
Reply marktyers (16) 9/14/2010 8:46:40 PM

marktyers <marktyers@gmail.com> wrote:

> However I have a follow-up question. How can I round up the reals to 2
> decimal places? At the moment they are accurate to 7 which causes a
> few wobbles:
> 
>    55.990002
>    28.500000
>    12.990000
>    18.500000
>    5.9899998
>    55.680000
>    24.980000

You should probably read up a bit on floatting point. That is an
incredibly important subject, which will bite you hard if you don't
understand a few basics.

One of the most important things to realize is that reals are almost
always stored internally in a binary form rather than a decimal one. (In
fact, it might be more accurate to just say "always" because you won't
actually find any exceptions. The standard allows for exceptions, there
might have been one or two odd cases in history, and maybe someday there
will be some, but you won't find any today - not in Fortran compilers.)

There is no such value as, for example, 55.99 in binary. Nor is there a
55.990002. Those are both just approximations to the binary value; they
are not exact.

You can print out values rounded to 2 decimal places (or with all kinds
of other options) using an explicit format instead of the *. See the
format statement (which has enough options to be almost a language into
itself). For a simple example in your case, you could do

  write (*,'(f10.2)') c

But inderstand that this does *NOT* make the actual value of c be
somehow rounded to 2 decimal places. It just rounds the printed output.
If you do enough calculations with c, the difference can matter.

-- 
Richard Maine                    | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle           |  -- Mark Twain
0
Reply nospam 9/14/2010 9:02:33 PM

On Tue, 14 Sep 2010 13:46:40 -0700 (PDT), marktyers <marktyers@gmail.com>
 wrote in <c1f7704e-f3b9-4e32-880a-902721693241@y31g2000vbt.googlegroups.com>:
>       		print *,c

> However I have a follow-up question. How can I round up the reals to 2
> decimal places? At the moment they are accurate to 7 which causes a
> few wobbles:

>    55.990002
>    28.500000
>    12.990000
>    18.500000
>    5.9899998
>    55.680000
>    24.980000

	Wobbles in which way?  You are using a free format which allows 
the "processor" (i.e. compiler) to choose however it wishes to express the 
(inexact!) floating-point representation of your fractional monetary 
amounts.  The most sensible answer is to choose your own format for the 
output:

	write(*,'(F8.2)') c

	Now you just have to worry about rounding modes...  :-)

-- 
Ivan Reid, School of Engineering & Design, _____________  CMS Collaboration,
Brunel University.    Ivan.Reid@[brunel.ac.uk|cern.ch]    Room 40-1-B12, CERN
        KotPT -- "for stupidity above and beyond the call of duty".
0
Reply Dr 9/14/2010 9:06:51 PM

On Sep 14, 4:46=A0pm, marktyers <markty...@gmail.com> wrote:
> On Sep 14, 9:34=A0pm, nos...@see.signature (Richard Maine) wrote:
>

> > marktyers <markty...@gmail.com> wrote:
> > > I am learning fortran by writing a series of short programs and have
> > > met with some success! I am having a few problems with the one that
> > > reads data from a text file and keeps a running total of a cost. The
> > > CSV file contains the following:
>
> > > fuel,SMITH,55.99
> > > accomodation,SMITH,28.50
> > > food,SMITH,12.99
> > > food,JONES,18.50
> > > books,JONES,5.99
> > > accomodation,SMITH,55.68
> > > books,SMITH,24.98
>
> > > My Fortran program looks like this:
>
> > > =A0 =A0 =A0 ! a simple fortran program to read a csv file
> > > =A0 =A0 =A0 ! containing expenses data, print off each cost
> > > =A0 =A0 =A0 ! and keep a running total
> > > =A0 =A0 =A0 program fileread
> > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 character*16 a
> > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 character*16 b
> > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 character*16 c
> > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 open(unit=3D1, file=3D'expenses.txt')
> > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 do while(.true.)
> > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 read (1,*,end=3D99) a, b,=
 c
> > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 print *,c
> > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 enddo
> > > 99 =A0 =A0 =A0continue
> > > =A0 =A0 =A0 end program fileread
>
> > > The next step is to create a float variable called total and use it t=
o
> > > keep a running total of the costs. The problem is how to I convert
> > > each of the expense values into a float so I can add them up.
>
> > > Can anyone help?
>
> > Well, it would seem easier to just have c be a real in the first place.
> > I just took your above code and file as is, changing nothing except for
> > the declaration of c, and it worked fine.
>
> > If there is some particular other reason why you want c to be character
> > (which there might be), then what you want is called an internal read.
> > An internal read looks just like a "normal" (external file) read except
> > that you are reading from a character variable instead of from a file.
> > For example
>
> > =A0 =A0read(c,*) x
>
> > would do the trick in your case, where x is a real variable.
>
> > While trying out this code (to make sure I was telling the truth when I
> > said that it worked with just the declaration change), I did notice two
> > small things that I'll comment on.
>
> > 1. Using single-digit unit numbers is generally inadvisable. They often
> > have special uses that canconflict with your use. The most common
> > special-use unit numbers are 5 and 6, but the details do vary among
> > compilers. It is best to just avoid single digit ones at all. It is
> > unfortunate that the language makes you have to choose a numeric
> > identifier for a unit, and then places these pitfalls in the way of you=
r
> > choice, but that's historical (or, as they sometomes say, hysterical).
>
> > 2. "do while(.true.)" is a strange pseudo-Pascalism that has worked its
> > way into some people's Fortran style, possibly because there was a time
> > when "DO while" was a common Fortran extension, but the unadorned DO wa=
s
> > not. It is more simply spelled as just plain
>
> > =A0 DO
>
> > Nothing more. The while(.true.) part is not needed.
>
> Thanks for both the replies. I have tweaked my program thus:
>
> =A0 =A0 =A0 ! a simple fortran program to read a csv file
> =A0 =A0 =A0 ! containing expenses data, print off each cost
> =A0 =A0 =A0 ! and keep a running total
> =A0 =A0 =A0 program fileread
> =A0 =A0 =A0 =A0 character*16 a
> =A0 =A0 =A0 =A0 character*16 b
> =A0 =A0 =A0 =A0 real c
> =A0 =A0 =A0 =A0 real cost
> =A0 =A0 =A0 =A0 real total =3D 0.0
> =A0 =A0 =A0 =A0 open(unit=3D10, file=3D'expenses.txt')
> =A0 =A0 =A0 =A0 do
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 read (10,*,end=3D99) a, b, c
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 print *,c
> =A0 =A0 =A0 =A0 enddo
> 99 =A0 =A0 =A0continue
> =A0 =A0 =A0 end program fileread
>
> and it works!
>
> However I have a follow-up question. How can I round up the reals to 2
> decimal places? At the moment they are accurate to 7 which causes a
> few wobbles:
>
> =A0 =A055.990002
> =A0 =A028.500000
> =A0 =A012.990000
> =A0 =A018.500000
> =A0 =A05.9899998
> =A0 =A055.680000
> =A0 =A024.980000

multiply each value by 100, add a "fudge factor", take the integer,
and pray.
sum.
divide by 100, output and pray.

Probably the most robust method is to take the input as a character
variable, eliminate the decimal point character and read the value as
a integer. Sum as an integer, output as an integer, convert back to
dollars and cents (or whatever currency) as a character variable.

IIRC you are teaching students with this, so showing them a
spectacular failure might be good way to help them understand why
there are business programming languages (like COBOL) which support
decimal arithmetic. [In COBOL you run into the problem of de-editing
out the decimal point, but that's another story.]

--- Elliot





0
Reply epc8 (1259) 9/14/2010 9:27:37 PM

On Sep 15, 9:27=A0am, e p chandler <e...@juno.com> wrote:
> On Sep 14, 4:46=A0pm, marktyers <markty...@gmail.com> wrote:
>
>
>
> > On Sep 14, 9:34=A0pm, nos...@see.signature (Richard Maine) wrote:
>
> > > marktyers <markty...@gmail.com> wrote:
> > > > I am learning fortran by writing a series of short programs and hav=
e
> > > > met with some success! I am having a few problems with the one that
> > > > reads data from a text file and keeps a running total of a cost. Th=
e
> > > > CSV file contains the following:
>
> > > > fuel,SMITH,55.99
> > > > accomodation,SMITH,28.50
> > > > food,SMITH,12.99
> > > > food,JONES,18.50
> > > > books,JONES,5.99
> > > > accomodation,SMITH,55.68
> > > > books,SMITH,24.98
>
> > > > My Fortran program looks like this:
>
> > > > =A0 =A0 =A0 ! a simple fortran program to read a csv file
> > > > =A0 =A0 =A0 ! containing expenses data, print off each cost
> > > > =A0 =A0 =A0 ! and keep a running total
> > > > =A0 =A0 =A0 program fileread
> > > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 character*16 a
> > > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 character*16 b
> > > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 character*16 c
> > > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 open(unit=3D1, file=3D'expenses.txt')
> > > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 do while(.true.)
> > > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 read (1,*,end=3D99) a, =
b, c
> > > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 print *,c
> > > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 enddo
> > > > 99 =A0 =A0 =A0continue
> > > > =A0 =A0 =A0 end program fileread
>
> > > > The next step is to create a float variable called total and use it=
 to
> > > > keep a running total of the costs. The problem is how to I convert
> > > > each of the expense values into a float so I can add them up.
>
> > > > Can anyone help?
>
> > > Well, it would seem easier to just have c be a real in the first plac=
e.
> > > I just took your above code and file as is, changing nothing except f=
or
> > > the declaration of c, and it worked fine.
>
> > > If there is some particular other reason why you want c to be charact=
er
> > > (which there might be), then what you want is called an internal read=
..
> > > An internal read looks just like a "normal" (external file) read exce=
pt
> > > that you are reading from a character variable instead of from a file=
..
> > > For example
>
> > > =A0 =A0read(c,*) x
>
> > > would do the trick in your case, where x is a real variable.
>
> > > While trying out this code (to make sure I was telling the truth when=
 I
> > > said that it worked with just the declaration change), I did notice t=
wo
> > > small things that I'll comment on.
>
> > > 1. Using single-digit unit numbers is generally inadvisable. They oft=
en
> > > have special uses that canconflict with your use. The most common
> > > special-use unit numbers are 5 and 6, but the details do vary among
> > > compilers. It is best to just avoid single digit ones at all. It is
> > > unfortunate that the language makes you have to choose a numeric
> > > identifier for a unit, and then places these pitfalls in the way of y=
our
> > > choice, but that's historical (or, as they sometomes say, hysterical)=
..
>
> > > 2. "do while(.true.)" is a strange pseudo-Pascalism that has worked i=
ts
> > > way into some people's Fortran style, possibly because there was a ti=
me
> > > when "DO while" was a common Fortran extension, but the unadorned DO =
was
> > > not. It is more simply spelled as just plain
>
> > > =A0 DO
>
> > > Nothing more. The while(.true.) part is not needed.
>
> > Thanks for both the replies. I have tweaked my program thus:
>
> > =A0 =A0 =A0 ! a simple fortran program to read a csv file
> > =A0 =A0 =A0 ! containing expenses data, print off each cost
> > =A0 =A0 =A0 ! and keep a running total
> > =A0 =A0 =A0 program fileread
> > =A0 =A0 =A0 =A0 character*16 a
> > =A0 =A0 =A0 =A0 character*16 b
> > =A0 =A0 =A0 =A0 real c
> > =A0 =A0 =A0 =A0 real cost
> > =A0 =A0 =A0 =A0 real total =3D 0.0
> > =A0 =A0 =A0 =A0 open(unit=3D10, file=3D'expenses.txt')
> > =A0 =A0 =A0 =A0 do
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 read (10,*,end=3D99) a, b, c
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 print *,c
> > =A0 =A0 =A0 =A0 enddo
> > 99 =A0 =A0 =A0continue
> > =A0 =A0 =A0 end program fileread
>
> > and it works!
>
> > However I have a follow-up question. How can I round up the reals to 2
> > decimal places? At the moment they are accurate to 7 which causes a
> > few wobbles:
>
> > =A0 =A055.990002
> > =A0 =A028.500000
> > =A0 =A012.990000
> > =A0 =A018.500000
> > =A0 =A05.9899998
> > =A0 =A055.680000
> > =A0 =A024.980000
>
> multiply each value by 100, add a "fudge factor", take the integer,
> and pray.
> sum.
> divide by 100, output and pray.
>
> Probably the most robust method is to take the input as a character
> variable, eliminate the decimal point character and read the value as
> a integer. Sum as an integer, output as an integer, convert back to
> dollars and cents (or whatever currency) as a character variable.
>
> IIRC you are teaching students with this, so showing them a
> spectacular failure might be good way to help them understand why
> there are business programming languages (like COBOL) which support
> decimal arithmetic. [In COBOL you run into the problem of de-editing
> out the decimal point, but that's another story.]
>
> --- Elliot

Spectacular failures can also happen with integers. Many systems have
32-bit integers which will overflow with amounts over $21,474,836.47
(which may be outside your own financial limits, but I hope not
outside a bank's!) Consider the following program and its output on
such a system:

implicit none
integer:: n =3D 100, i
do i =3D 1,10
   n =3D n*10
   print *,n
end do
end

 100
 1000
 10000
 100000
 1000000
 10000000
 100000000
 1000000000
 1410065408
 1215752192
 -727379968
0
Reply john.harper (194) 9/14/2010 9:59:35 PM

On 2010-09-14 18:27:37 -0300, e p chandler <epc8@juno.com> said:

> On Sep 14, 4:46�pm, marktyers <markty...@gmail.com> wrote:
>> On Sep 14, 9:34�pm, nos...@see.signature (Richard Maine) wrote:
>> 
> 
>>> marktyers <markty...@gmail.com> wrote:
>>>> I am learning fortran by writing a series of short programs and have
>>>> met with some success! I am having a few problems with the one that
>>>> reads data from a text file and keeps a running total of a cost. The
>>>> CSV file contains the following:
>> 
>>>> fuel,SMITH,55.99
>>>> accomodation,SMITH,28.50
>>>> food,SMITH,12.99
>>>> food,JONES,18.50
>>>> books,JONES,5.99
>>>> accomodation,SMITH,55.68
>>>> books,SMITH,24.98
>> 
>>>> My Fortran program looks like this:
>> 
>>>> � � � ! a simple fortran program to read a csv file
>>>> � � � ! containing expenses data, print off each cost
>>>> � � � ! and keep a running total
>>>> � � � program fileread
>>>> � � � � � � � character*16 a
>>>> � � � � � � � character*16 b
>>>> � � � � � � � character*16 c
>>>> � � � � � � � open(unit=1, file='expenses.txt')
>>>> � � � � � � � do while(.true.)
>>>> � � � � � � � � � � � read (1,*,end=99) a, b,
>  c
>>>> � � � � � � � � � � � print *,c
>>>> � � � � � � � enddo
>>>> 99 � � �continue
>>>> � � � end program fileread
>> 
>>>> The next step is to create a float variable called total and use it t
> o
>>>> keep a running total of the costs. The problem is how to I convert
>>>> each of the expense values into a float so I can add them up.
>> 
>>>> Can anyone help?
>> 
>>> Well, it would seem easier to just have c be a real in the first place.
>>> I just took your above code and file as is, changing nothing except for
>>> the declaration of c, and it worked fine.
>> 
>>> If there is some particular other reason why you want c to be character
>>> (which there might be), then what you want is called an internal read.
>>> An internal read looks just like a "normal" (external file) read except
>>> that you are reading from a character variable instead of from a file.
>>> For example
>> 
>>> � �read(c,*) x
>> 
>>> would do the trick in your case, where x is a real variable.
>> 
>>> While trying out this code (to make sure I was telling the truth when I
>>> said that it worked with just the declaration change), I did notice two
>>> small things that I'll comment on.
>> 
>>> 1. Using single-digit unit numbers is generally inadvisable. They often
>>> have special uses that canconflict with your use. The most common
>>> special-use unit numbers are 5 and 6, but the details do vary among
>>> compilers. It is best to just avoid single digit ones at all. It is
>>> unfortunate that the language makes you have to choose a numeric
>>> identifier for a unit, and then places these pitfalls in the way of you
> r
>>> choice, but that's historical (or, as they sometomes say, hysterical).
>> 
>>> 2. "do while(.true.)" is a strange pseudo-Pascalism that has worked its
>>> way into some people's Fortran style, possibly because there was a time
>>> when "DO while" was a common Fortran extension, but the unadorned DO wa
> s
>>> not. It is more simply spelled as just plain
>> 
>>> � DO
>> 
>>> Nothing more. The while(.true.) part is not needed.
>> 
>> Thanks for both the replies. I have tweaked my program thus:
>> 
>> � � � ! a simple fortran program to read a csv file
>> � � � ! containing expenses data, print off each cost
>> � � � ! and keep a running total
>> � � � program fileread
>> � � � � character*16 a
>> � � � � character*16 b
>> � � � � real c
>> � � � � real cost
>> � � � � real total = 0.0
>> � � � � open(unit=10, file='expenses.txt')
>> � � � � do
>> � � � � � � � � read (10,*,end=99) a, b, c
>> � � � � � � � � print *,c
>> � � � � enddo
>> 99 � � �continue
>> � � � end program fileread
>> 
>> and it works!
>> 
>> However I have a follow-up question. How can I round up the reals to 2
>> decimal places? At the moment they are accurate to 7 which causes a
>> few wobbles:
>> 
>> � �55.990002
>> � �28.500000
>> � �12.990000
>> � �18.500000
>> � �5.9899998
>> � �55.680000
>> � �24.980000
> 
> multiply each value by 100, add a "fudge factor", take the integer,
> and pray.
> sum.
> divide by 100, output and pray.

Nonbelievers can just use NINT which is the nearest integer. So try

 x=anint(x*100.0)/100.0

where anint is the real version of nint.

> Probably the most robust method is to take the input as a character
> variable, eliminate the decimal point character and read the value as
> a integer. Sum as an integer, output as an integer, convert back to
> dollars and cents (or whatever currency) as a character variable.
> 
> IIRC you are teaching students with this, so showing them a
> spectacular failure might be good way to help them understand why
> there are business programming languages (like COBOL) which support
> decimal arithmetic. [In COBOL you run into the problem of de-editing
> out the decimal point, but that's another story.]
> 
> --- Elliot


0
Reply Gordon.Sande1 (250) 9/14/2010 10:10:13 PM

Richard Maine <nospam@see.signature> wrote:
(snip)
 
> One of the most important things to realize is that reals are almost
> always stored internally in a binary form rather than a decimal one. (In
> fact, it might be more accurate to just say "always" because you won't
> actually find any exceptions. The standard allows for exceptions, there
> might have been one or two odd cases in history, and maybe someday there
> will be some, but you won't find any today - not in Fortran compilers.)

I believe IBM has some machines with the new IEEE decimal float
in production, though, as far as I know, no Fortran support for it.

-- glen
0
Reply glen 9/14/2010 10:57:53 PM

Richard Maine <nospam@see.signature> wrote:
(snip)
 
> You can print out values rounded to 2 decimal places (or with all kinds
> of other options) using an explicit format instead of the *. See the
> format statement (which has enough options to be almost a language into
> itself). For a simple example in your case, you could do
 
>  write (*,'(f10.2)') c
 
> But inderstand that this does *NOT* make the actual value of c be
> somehow rounded to 2 decimal places. It just rounds the printed output.
> If you do enough calculations with c, the difference can matter.

Among others, if you print out the numbers rounded, but sum the
unrounded binary values, the rounded sum can be different from the
sum of the rounded values.  Not so likely if the input values have
no more decimal places than the rounded values, but still possible.

-- glen 
0
Reply gah (12236) 9/14/2010 11:01:34 PM

On 14-9-2010 23:59, jfh wrote:
> Spectacular failures can also happen with integers. Many systems have
> 32-bit integers which will overflow with amounts over $21,474,836.47
> (which may be outside your own financial limits, but I hope not
> outside a bank's!) Consider the following program and its output on
> such a system:
>
> implicit none
> integer:: n = 100, i
> do i = 1,10
>     n = n*10
>     print *,n
> end do
> end
>
>   100
>   1000
>   10000
>   100000
>   1000000
>   10000000
>   100000000
>   1000000000
>   1410065408
>   1215752192
>   -727379968

Kind of looks like what happened to the global economy, doesn't it? ;)

Erik.
0
Reply Erik 9/14/2010 11:31:31 PM

glen herrmannsfeldt <gah@ugcs.caltech.edu> wrote:

> Richard Maine <nospam@see.signature> wrote:
>  
> > One of the most important things to realize is that reals are almost
> > always stored internally in a binary form rather than a decimal one. (In
> > fact, it might be more accurate to just say "always" because you won't
> > actually find any exceptions. The standard allows for exceptions, there
> > might have been one or two odd cases in history, and maybe someday there
> > will be some, but you won't find any today - not in Fortran compilers.)
> 
> I believe IBM has some machines with the new IEEE decimal float
> in production, though, as far as I know, no Fortran support for it.

That's exactly why I said "not in Fortran compilers." (And note I also
said "today".)

-- 
Richard Maine                    | Good judgment comes from experience;
email: last name at domain . net | experience comes from bad judgment.
domain: summertriangle           |  -- Mark Twain
0
Reply nospam 9/14/2010 11:34:30 PM

Richard Maine <nospam@see.signature> wrote:
> glen herrmannsfeldt <gah@ugcs.caltech.edu> wrote:
>> Richard Maine <nospam@see.signature> wrote:
  
>> > One of the most important things to realize is that reals are almost
>> > always stored internally in a binary form rather than a decimal one. (In
>> > fact, it might be more accurate to just say "always" because you won't
>> > actually find any exceptions. The standard allows for exceptions, there
>> > might have been one or two odd cases in history, and maybe someday there
>> > will be some, but you won't find any today - not in Fortran compilers.)
 
>> I believe IBM has some machines with the new IEEE decimal float
>> in production, though, as far as I know, no Fortran support for it.
 
> That's exactly why I said "not in Fortran compilers." (And note I also
> said "today".)

I was mostly trying to agree with you, though with a hint that there
may be some in the near future.  Note that there aren't any trinary
floating point machines, nor Fortran compilers today, I don't know
that anyone is working on one, and would be really surprised to
see one.  Still, the standard allows for trinary in case anyone
decides to support it.  I suppose one could do it in software
emulation, but not likely in hardware.

-- glen 
0
Reply glen 9/14/2010 11:49:28 PM

"jfh" <john.harper@vuw.ac.nz> wrote

Spectacular failures can also happen with integers. Many systems have
32-bit integers which will overflow with amounts over $21,474,836.47
(which may be outside your own financial limits, but I hope not
outside a bank's!) Consider the following program and its output on
such a system:

implicit none
integer:: n = 100, i
do i = 1,10
   n = n*10
   print *,n
end do
end

 100
 1000
 10000
 100000
 1000000
 10000000
 100000000
 1000000000
 1410065408
 1215752192
 -727379968

-----> Ouch. I too tired to make political jokes about this.

0
Reply e 9/15/2010 12:22:08 AM

"e p chandler" <epc8@juno.com> wrote in message 
news:a3590cbf-344e-400a-b5d1-2aea323ed5cb@m16g2000vbs.googlegroups.com...

>IIRC you are teaching students with this, so showing them a
>spectacular failure might be good way to help them understand why
>there are business programming languages (like COBOL)

and general-puspose languages such as PL/I

> which support
>decimal arithmetic. [In COBOL you run into the problem of de-editing
>out the decimal point,

but not in PL/I, which handles decimal fixed-point with and without
decimal points. 


0
Reply robin 9/15/2010 12:42:01 AM

"jfh" <john.harper@vuw.ac.nz> wrote in message news:269168e4-39b5-4d08-9d99-3272cddedf8a@s17g2000prh.googlegroups.com...

>Spectacular failures can also happen with integers. Many systems have
>32-bit integers which will overflow with amounts over $21,474,836.47
>(which may be outside your own financial limits, but I hope not
>outside a bank's!) Consider the following program and its output on
>such a system:

>implicit none
>integer:: n = 100, i
>do i = 1,10
>   n = n*10
>   print *,n
>end do
>end

> 100
> 1000
> 10000
> 100000
> 1000000
> 10000000
> 100000000
> 1000000000
> 1410065408
> 1215752192
> -727379968

This doesn't happen with PL/I, which traps such overflows
and gives an informative message.

In any case, IBM's PL/I has decimal arithmetic that provides up to
around 30 decimal digits. 


0
Reply robin 9/15/2010 12:46:53 AM

On 2010-09-14 20:34:30 -0300, nospam@see.signature (Richard Maine) said:

> glen herrmannsfeldt <gah@ugcs.caltech.edu> wrote:
> 
>> Richard Maine <nospam@see.signature> wrote:
>> 
>>> One of the most important things to realize is that reals are almost
>>> always stored internally in a binary form rather than a decimal one. (In
>>> fact, it might be more accurate to just say "always" because you won't
>>> actually find any exceptions. The standard allows for exceptions, there
>>> might have been one or two odd cases in history, and maybe someday there
>>> will be some, but you won't find any today - not in Fortran compilers.)
>> 
>> I believe IBM has some machines with the new IEEE decimal float
>> in production, though, as far as I know, no Fortran support for it.
> 
> That's exactly why I said "not in Fortran compilers." (And note I also
> said "today".)

I have a strong impression that one of the options for a Microsoft Fortran
compiler of DOS 3.3 vintage was to use its alternate floating point packeage
which used BCD arithemetic. That was back when the x87 chip was not a standard
feature of PCs.


0
Reply Gordon 9/15/2010 1:24:04 AM

Gordon Sande <Gordon.Sande@gmail.com> wrote:
(snip on decimal float and Fortran)
 
>> That's exactly why I said "not in Fortran compilers." (And note I also
>> said "today".)
 
> I have a strong impression that one of the options for a Microsoft Fortran
> compiler of DOS 3.3 vintage was to use its alternate floating point packeage
> which used BCD arithemetic. That was back when the x87 chip was not a standard
> feature of PCs.

I have heard it back to the IBM 650, which was basically a decimal
machine.  As far as I understand, the floating point was done in
software using the decimal fixed point hardware.  

Most hand calculators do decimal arithmetic (BCD), including
floating point.  Most don't have a Fortran compiler.

The IBM z/Architecture is used on high end IBM machine, and
is still being actively developed.  

-- glen
0
Reply glen 9/15/2010 1:30:41 AM

"robin" <robin51@dodo.com.au> wrote in message 
news:4c901660$0$67832$c30e37c6@exi-reader.telstra.net...
> "e p chandler" <epc8@juno.com> wrote in message
> news:a3590cbf-344e-400a-b5d1-2aea323ed5cb@m16g2000vbs.googlegroups.com...
>
>>IIRC you are teaching students with this, so showing them a
>>spectacular failure might be good way to help them understand why
>>there are business programming languages (like COBOL)
>
> and general-puspose languages such as PL/I
>
>> which support
>>decimal arithmetic. [In COBOL you run into the problem of de-editing
>>out the decimal point,
>
You might want to post this in comp.lang.cobol

COBOL supports both edited and non-edited numeric fields.  The NUMVAL (and 
NUMVAL-C) intrinsic functions have been available since 1989 to support the 
use of edited fields in arithmetic expressions.

(Sorry to post off-topic, but I couldn't let this implication go)

P.S.  On the other cross-posted note, current IBM Enterprise COBOL (and for 
several years now) fully supports 31-digit numeric fields and results (see 
the ARITH compiler option).  It doesn't yet support decimal floating point, 
but requirements for such have been accepted. 


0
Reply Bill 9/15/2010 4:41:19 AM

On Sep 15, 6:46=A0am, marktyers <markty...@gmail.com> wrote:
> On Sep 14, 9:34=A0pm, nos...@see.signature (Richard Maine) wrote:
>
>
>
>
>
> > marktyers <markty...@gmail.com> wrote:
> > > I am learning fortran by writing a series of short programs and have
> > > met with some success! I am having a few problems with the one that
> > > reads data from a text file and keeps a running total of a cost. The
> > > CSV file contains the following:
>
> > > fuel,SMITH,55.99
> > > accomodation,SMITH,28.50
> > > food,SMITH,12.99
> > > food,JONES,18.50
> > > books,JONES,5.99
> > > accomodation,SMITH,55.68
> > > books,SMITH,24.98
>
> > > My Fortran program looks like this:
>
> > > =A0 =A0 =A0 ! a simple fortran program to read a csv file
> > > =A0 =A0 =A0 ! containing expenses data, print off each cost
> > > =A0 =A0 =A0 ! and keep a running total
> > > =A0 =A0 =A0 program fileread
> > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 character*16 a
> > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 character*16 b
> > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 character*16 c
> > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 open(unit=3D1, file=3D'expenses.txt')
> > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 do while(.true.)
> > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 read (1,*,end=3D99) a, b,=
 c
> > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 print *,c
> > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 enddo
> > > 99 =A0 =A0 =A0continue
> > > =A0 =A0 =A0 end program fileread
>
> > > The next step is to create a float variable called total and use it t=
o
> > > keep a running total of the costs. The problem is how to I convert
> > > each of the expense values into a float so I can add them up.
>
> > > Can anyone help?
>
> > Well, it would seem easier to just have c be a real in the first place.
> > I just took your above code and file as is, changing nothing except for
> > the declaration of c, and it worked fine.
>
> > If there is some particular other reason why you want c to be character
> > (which there might be), then what you want is called an internal read.
> > An internal read looks just like a "normal" (external file) read except
> > that you are reading from a character variable instead of from a file.
> > For example
>
> > =A0 =A0read(c,*) x
>
> > would do the trick in your case, where x is a real variable.
>
> > While trying out this code (to make sure I was telling the truth when I
> > said that it worked with just the declaration change), I did notice two
> > small things that I'll comment on.
>
> > 1. Using single-digit unit numbers is generally inadvisable. They often
> > have special uses that canconflict with your use. The most common
> > special-use unit numbers are 5 and 6, but the details do vary among
> > compilers. It is best to just avoid single digit ones at all. It is
> > unfortunate that the language makes you have to choose a numeric
> > identifier for a unit, and then places these pitfalls in the way of you=
r
> > choice, but that's historical (or, as they sometomes say, hysterical).
>
> > 2. "do while(.true.)" is a strange pseudo-Pascalism that has worked its
> > way into some people's Fortran style, possibly because there was a time
> > when "DO while" was a common Fortran extension, but the unadorned DO wa=
s
> > not. It is more simply spelled as just plain
>
> > =A0 DO
>
> > Nothing more. The while(.true.) part is not needed.
>
> > --
> > Richard Maine =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0| Good judgment co=
mes from experience;
> > email: last name at domain . net | experience comes from bad judgment.
> > domain: summertriangle =A0 =A0 =A0 =A0 =A0 | =A0-- Mark Twain
>
> Thanks for both the replies. I have tweaked my program thus:
>
> =A0 =A0 =A0 ! a simple fortran program to read a csv file
> =A0 =A0 =A0 ! containing expenses data, print off each cost
> =A0 =A0 =A0 ! and keep a running total
> =A0 =A0 =A0 program fileread
> =A0 =A0 =A0 =A0 character*16 a
> =A0 =A0 =A0 =A0 character*16 b
> =A0 =A0 =A0 =A0 real c
> =A0 =A0 =A0 =A0 real cost
> =A0 =A0 =A0 =A0 real total =3D 0.0
> =A0 =A0 =A0 =A0 open(unit=3D10, file=3D'expenses.txt')
> =A0 =A0 =A0 =A0 do
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 read (10,*,end=3D99) a, b, c
> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 print *,c
> =A0 =A0 =A0 =A0 enddo
> 99 =A0 =A0 =A0continue
> =A0 =A0 =A0 end program fileread
>
> and it works!
>
> However I have a follow-up question. How can I round up the reals to 2
> decimal places? At the moment they are accurate to 7 which causes a
> few wobbles:
>
> =A0 =A055.990002
> =A0 =A028.500000
> =A0 =A012.990000
> =A0 =A018.500000
> =A0 =A05.9899998
> =A0 =A055.680000
> =A0 =A024.980000
>
> thanks
> Mark

There is a better way; all of the advice is good, but when using
Fortran to do accounting work, you MUST count in whole integers of
money; this can be all cents, or separate totals of cents and units
(e.g. dollars, pesos, etc)

Now theory requires you to read in the money field as a character
string and extract the dollars and cents separately. However, it is
more parctical to use real varibles as you have been advised. Then,
after reading the value, add 0.0045 to a positive value (or subtract
from a negative one), and assign the result to an integer (converting
the rounded up dollar amount to an integer, then subtract this integer
value from the rounded-up real value and multiply the rel result by
100.0 and this result is the signed number of cents.

Now do any aritmetic separately, remebering to convert the cents to
whole dollars and remaing cents at some stage.
0
Reply tbwright (1098) 9/17/2010 4:55:27 AM

On Sep 15, 7:27=A0am, e p chandler <e...@juno.com> wrote:
> On Sep 14, 4:46=A0pm, marktyers <markty...@gmail.com> wrote:
>
>
>
>
>
> > On Sep 14, 9:34=A0pm, nos...@see.signature (Richard Maine) wrote:
>
> > > marktyers <markty...@gmail.com> wrote:
> > > > I am learning fortran by writing a series of short programs and hav=
e
> > > > met with some success! I am having a few problems with the one that
> > > > reads data from a text file and keeps a running total of a cost. Th=
e
> > > > CSV file contains the following:
>
> > > > fuel,SMITH,55.99
> > > > accomodation,SMITH,28.50
> > > > food,SMITH,12.99
> > > > food,JONES,18.50
> > > > books,JONES,5.99
> > > > accomodation,SMITH,55.68
> > > > books,SMITH,24.98
>
> > > > My Fortran program looks like this:
>
> > > > =A0 =A0 =A0 ! a simple fortran program to read a csv file
> > > > =A0 =A0 =A0 ! containing expenses data, print off each cost
> > > > =A0 =A0 =A0 ! and keep a running total
> > > > =A0 =A0 =A0 program fileread
> > > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 character*16 a
> > > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 character*16 b
> > > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 character*16 c
> > > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 open(unit=3D1, file=3D'expenses.txt')
> > > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 do while(.true.)
> > > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 read (1,*,end=3D99) a, =
b, c
> > > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 print *,c
> > > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 enddo
> > > > 99 =A0 =A0 =A0continue
> > > > =A0 =A0 =A0 end program fileread
>
> > > > The next step is to create a float variable called total and use it=
 to
> > > > keep a running total of the costs. The problem is how to I convert
> > > > each of the expense values into a float so I can add them up.
>
> > > > Can anyone help?
>
> > > Well, it would seem easier to just have c be a real in the first plac=
e.
> > > I just took your above code and file as is, changing nothing except f=
or
> > > the declaration of c, and it worked fine.
>
> > > If there is some particular other reason why you want c to be charact=
er
> > > (which there might be), then what you want is called an internal read=
..
> > > An internal read looks just like a "normal" (external file) read exce=
pt
> > > that you are reading from a character variable instead of from a file=
..
> > > For example
>
> > > =A0 =A0read(c,*) x
>
> > > would do the trick in your case, where x is a real variable.
>
> > > While trying out this code (to make sure I was telling the truth when=
 I
> > > said that it worked with just the declaration change), I did notice t=
wo
> > > small things that I'll comment on.
>
> > > 1. Using single-digit unit numbers is generally inadvisable. They oft=
en
> > > have special uses that canconflict with your use. The most common
> > > special-use unit numbers are 5 and 6, but the details do vary among
> > > compilers. It is best to just avoid single digit ones at all. It is
> > > unfortunate that the language makes you have to choose a numeric
> > > identifier for a unit, and then places these pitfalls in the way of y=
our
> > > choice, but that's historical (or, as they sometomes say, hysterical)=
..
>
> > > 2. "do while(.true.)" is a strange pseudo-Pascalism that has worked i=
ts
> > > way into some people's Fortran style, possibly because there was a ti=
me
> > > when "DO while" was a common Fortran extension, but the unadorned DO =
was
> > > not. It is more simply spelled as just plain
>
> > > =A0 DO
>
> > > Nothing more. The while(.true.) part is not needed.
>
> > Thanks for both the replies. I have tweaked my program thus:
>
> > =A0 =A0 =A0 ! a simple fortran program to read a csv file
> > =A0 =A0 =A0 ! containing expenses data, print off each cost
> > =A0 =A0 =A0 ! and keep a running total
> > =A0 =A0 =A0 program fileread
> > =A0 =A0 =A0 =A0 character*16 a
> > =A0 =A0 =A0 =A0 character*16 b
> > =A0 =A0 =A0 =A0 real c
> > =A0 =A0 =A0 =A0 real cost
> > =A0 =A0 =A0 =A0 real total =3D 0.0
> > =A0 =A0 =A0 =A0 open(unit=3D10, file=3D'expenses.txt')
> > =A0 =A0 =A0 =A0 do
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 read (10,*,end=3D99) a, b, c
> > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 print *,c
> > =A0 =A0 =A0 =A0 enddo
> > 99 =A0 =A0 =A0continue
> > =A0 =A0 =A0 end program fileread
>
> > and it works!
>
> > However I have a follow-up question. How can I round up the reals to 2
> > decimal places? At the moment they are accurate to 7 which causes a
> > few wobbles:
>
> > =A0 =A055.990002
> > =A0 =A028.500000
> > =A0 =A012.990000
> > =A0 =A018.500000
> > =A0 =A05.9899998
> > =A0 =A055.680000
> > =A0 =A024.980000
>
> multiply each value by 100, add a "fudge factor", take the integer,
> and pray.
> sum.
> divide by 100, output and pray.
>
> Probably the most robust method is to take the input as a character
> variable, eliminate the decimal point character and read the value as
> a integer. Sum as an integer, output as an integer, convert back to
> dollars and cents (or whatever currency) as a character variable.
>
> IIRC you are teaching students with this, so showing them a
> spectacular failure might be good way to help them understand why
> there are business programming languages (like COBOL) which support
> decimal arithmetic. [In COBOL you run into the problem of de-editing
> out the decimal point, but that's another story.]
>
> --- Elliot

Sorry, I missed Elliot's response which says much like I said. However
getting money amounts to square off in tables (for the beady eyes of
an auditor) can be a pain, unless you work in integers and do integer
arithmetic. (I wrote a lot of accounting software and spent two years
as an Auditor...).

And that old story of the bank programmer who did the accounting
software for a UK bank's foreign exchange change businees, where he
truncated the "amount times current rate" result and posted the final
fractions to his father-in-law's account.. - is true (and went to jail
for it).

0
Reply tbwright (1098) 9/17/2010 5:10:09 AM

On Sep 15, 9:59=A0am, jfh <john.har...@vuw.ac.nz> wrote:
> On Sep 15, 9:27=A0am, e p chandler <e...@juno.com> wrote:
>
>
>
> > On Sep 14, 4:46=A0pm, marktyers <markty...@gmail.com> wrote:
>
> > > On Sep 14, 9:34=A0pm, nos...@see.signature (Richard Maine) wrote:
>
> > > > marktyers <markty...@gmail.com> wrote:
> > > > > I am learning fortran by writing a series of short programs and h=
ave
> > > > > met with some success! I am having a few problems with the one th=
at
> > > > > reads data from a text file and keeps a running total of a cost. =
The
> > > > > CSV file contains the following:
>
> > > > > fuel,SMITH,55.99
> > > > > accomodation,SMITH,28.50
> > > > > food,SMITH,12.99
> > > > > food,JONES,18.50
> > > > > books,JONES,5.99
> > > > > accomodation,SMITH,55.68
> > > > > books,SMITH,24.98
>
> > > > > My Fortran program looks like this:
>
> > > > > =A0 =A0 =A0 ! a simple fortran program to read a csv file
> > > > > =A0 =A0 =A0 ! containing expenses data, print off each cost
> > > > > =A0 =A0 =A0 ! and keep a running total
> > > > > =A0 =A0 =A0 program fileread
> > > > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 character*16 a
> > > > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 character*16 b
> > > > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 character*16 c
> > > > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 open(unit=3D1, file=3D'expenses.txt')
> > > > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 do while(.true.)
> > > > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 read (1,*,end=3D99) a=
, b, c
> > > > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 print *,c
> > > > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 enddo
> > > > > 99 =A0 =A0 =A0continue
> > > > > =A0 =A0 =A0 end program fileread
>
> > > > > The next step is to create a float variable called total and use =
it to
> > > > > keep a running total of the costs. The problem is how to I conver=
t
> > > > > each of the expense values into a float so I can add them up.
>
> > > > > Can anyone help?
>
> > > > Well, it would seem easier to just have c be a real in the first pl=
ace.
> > > > I just took your above code and file as is, changing nothing except=
 for
> > > > the declaration of c, and it worked fine.
>
> > > > If there is some particular other reason why you want c to be chara=
cter
> > > > (which there might be), then what you want is called an internal re=
ad.
> > > > An internal read looks just like a "normal" (external file) read ex=
cept
> > > > that you are reading from a character variable instead of from a fi=
le.
> > > > For example
>
> > > > =A0 =A0read(c,*) x
>
> > > > would do the trick in your case, where x is a real variable.
>
> > > > While trying out this code (to make sure I was telling the truth wh=
en I
> > > > said that it worked with just the declaration change), I did notice=
 two
> > > > small things that I'll comment on.
>
> > > > 1. Using single-digit unit numbers is generally inadvisable. They o=
ften
> > > > have special uses that canconflict with your use. The most common
> > > > special-use unit numbers are 5 and 6, but the details do vary among
> > > > compilers. It is best to just avoid single digit ones at all. It is
> > > > unfortunate that the language makes you have to choose a numeric
> > > > identifier for a unit, and then places these pitfalls in the way of=
 your
> > > > choice, but that's historical (or, as they sometomes say, hysterica=
l).
>
> > > > 2. "do while(.true.)" is a strange pseudo-Pascalism that has worked=
 its
> > > > way into some people's Fortran style, possibly because there was a =
time
> > > > when "DO while" was a common Fortran extension, but the unadorned D=
O was
> > > > not. It is more simply spelled as just plain
>
> > > > =A0 DO
>
> > > > Nothing more. The while(.true.) part is not needed.
>
> > > Thanks for both the replies. I have tweaked my program thus:
>
> > > =A0 =A0 =A0 ! a simple fortran program to read a csv file
> > > =A0 =A0 =A0 ! containing expenses data, print off each cost
> > > =A0 =A0 =A0 ! and keep a running total
> > > =A0 =A0 =A0 program fileread
> > > =A0 =A0 =A0 =A0 character*16 a
> > > =A0 =A0 =A0 =A0 character*16 b
> > > =A0 =A0 =A0 =A0 real c
> > > =A0 =A0 =A0 =A0 real cost
> > > =A0 =A0 =A0 =A0 real total =3D 0.0
> > > =A0 =A0 =A0 =A0 open(unit=3D10, file=3D'expenses.txt')
> > > =A0 =A0 =A0 =A0 do
> > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 read (10,*,end=3D99) a, b, c
> > > =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 print *,c
> > > =A0 =A0 =A0 =A0 enddo
> > > 99 =A0 =A0 =A0continue
> > > =A0 =A0 =A0 end program fileread
>
> > > and it works!
>
> > > However I have a follow-up question. How can I round up the reals to =
2
> > > decimal places? At the moment they are accurate to 7 which causes a
> > > few wobbles:
>
> > > =A0 =A055.990002
> > > =A0 =A028.500000
> > > =A0 =A012.990000
> > > =A0 =A018.500000
> > > =A0 =A05.9899998
> > > =A0 =A055.680000
> > > =A0 =A024.980000
>
> > multiply each value by 100, add a "fudge factor", take the integer,
> > and pray.
> > sum.
> > divide by 100, output and pray.
>
> > Probably the most robust method is to take the input as a character
> > variable, eliminate the decimal point character and read the value as
> > a integer. Sum as an integer, output as an integer, convert back to
> > dollars and cents (or whatever currency) as a character variable.
>
> > IIRC you are teaching students with this, so showing them a
> > spectacular failure might be good way to help them understand why
> > there are business programming languages (like COBOL) which support
> > decimal arithmetic. [In COBOL you run into the problem of de-editing
> > out the decimal point, but that's another story.]
>
> > --- Elliot
>
> Spectacular failures can also happen with integers. Many systems have
> 32-bit integers which will overflow with amounts over $21,474,836.47
> (which may be outside your own financial limits, but I hope not
> outside a bank's!) Consider the following program and its output on
> such a system:
>
> implicit none
> integer:: n =3D 100, i
> do i =3D 1,10
> =A0 =A0n =3D n*10
> =A0 =A0print *,n
> end do
> end
>
> =A0100
> =A01000
> =A010000
> =A0100000
> =A01000000
> =A010000000
> =A0100000000
> =A01000000000
> =A01410065408
> =A01215752192
> =A0-727379968

Apologies: the program I gave is the one I intended to post, but it
does not give line 1 of that output. Instead it gives all the rest of
that output. Memo to myself: check _even more_ carefully that the
versions of programs I post really do produce the versions of output I
post :-(

-- John Harper
0
Reply john.harper (194) 9/19/2010 11:25:42 PM

22 Replies
757 Views

(page loaded in 0.476 seconds)

Similiar Articles:


















7/22/2012 9:29:12 PM


Reply: