Fortran: can’t get no leading zero

2008-08-28

Perhaps someone who eats Fortran for breakfast can help me.

Is it really the case that there’s no way (in (portable) Fortran) to format a floating point number so that it has as many leading zeros as are necessary to fill the field?

Imagine I wanted to output something like ISO 6709 and have the location of Sheffield displayed as:

+53.40-001.50

In Python (using C’s syntax) this is just '%+06.2f%+07.2f' % (lat,lon).

Can I really not do this in Fortran? Surely I have just missed something.

      WRITE(*,'(SP,F6.2,F7.2)')LAT,LON

gives me:

+53.40 -1.50

which is not what I wanted at all. I (half humourously) tried F06.2,F07.2 but that doesn’t work.

If true, it’s absolutely unforgivable.

About these ads

21 Responses to “Fortran: can’t get no leading zero”

  1. Nick Barnes Says:

    BZ?

  2. drj11 Says:

    Yeah. Tried that. NBG. Apparently that only does anything useful for input.

  3. Nick Barnes Says:

    http://www.fortran.com/fortran/F77_std/rjcnf0001-sh-13.html

    It looks as if you can prefill the output field with zeroes and then go back and write the number over it. Something like 6’0′,TL6,F6.2
    Yuck.

  4. Gareth Rees Says:

    Presumably you figured out how to do this anyway, right?

    WRITE (*,'(SP,i3.2,SS,f3.2,SP,i4.3,SS,f3.2)’) FLOOR(LAT), (LAT – FLOOR(LAT)), FLOOR(LON), (LON – FLOOR(LON))

  5. Gareth Rees Says:

    Oops: that only handles positive values of LAT and LON. So maybe something like

    WRITE (*,'(SP,i3.2,SS,f3.2,SP,i4.3,SS,f3.2)’) FLOOR(AINT(LAT)), ABS(LAT – AINT(LAT)), FLOOR(AINT(LON)), ABS((LON – AINT(LON)))

  6. Gareth Rees Says:

    No, that doesn’t work for values with modulus less than 1.

    OK, I have no idea how to do this in just one WRITE statement.

  7. Gareth Rees Says:

    So how about this (X is a dummy REAL variable needed for the SIGN procedure to work):

    WRITE (*,'(SP,f3.0,TL2,SS,i2.2,f3.2,SP,f3.0,TL2,SS,i3.3,f3.2)’) &
    SIGN(X,LAT),FLOOR(ABS(LAT)),ABS(LAT-AINT(LAT)),SIGN(X,LON),FLOOR(ABS(LON)),ABS(LON-AINT(LON))

  8. Gareth Rees Says:

    Not sure that was worth forty minutes’ effort.

  9. Nick Barnes Says:

    Hmm. I posted a reply here but it doesn’t seem to have appeared. You can pre-fill the field with zeroes and then use TL to go back and write the value.

  10. drj11 Says:

    @Nick: I have recovered your comment from the spam trap.

    I still have to get the sign right and in the right place, but clearly I can do that with more TLing. Gak.

  11. drj11 Says:

    Bottom line: I didn’t miss an easy fix.

  12. Gareth Rees Says:

    When I try Nick’s recipe, it doesn’t work because the spaces generated by the F output control overwrite the zeros. For example, when I run this statement in GNU Fortran 4.4.0:

    WRITE (*,”(‘000000′,TL5,f6.2)”) -45.2

    I get the output:

    0-45.20

    (Hence my recipe of 2008-08-30 at 11:37:40, which outputs the sign, integer part, and fractional part in separate controls.)

  13. Gareth Rees Says:

    No, that wasn’t what I meant to write. I meant that the sign goes in the wrong place.

    Not my day today.

  14. Rich Says:

    Ugly but easy:

    program spike
    character title*16
    double precision t

    t=3.1415926535

    write(title(1:8),'(f8.2)’) t
    write(title(1:5),'(i5.5)’) nint(t)
    write(*,*) title
    end

    • Oliver A Says:

      Shorter, does the (same) trick in one line:

      t = 3.14159
      write(*,'(F8.2,TL8,I5.5)’) t, nint(t)

      Oliver

      • drj11 Says:

        Funny. But don’t, whatever you do, try it with 2.718. NINT indeed.

        And I’m not just being snarky, this is a genuine problem. I’m not a Fortran expert and I do not know what the correct coercion is.

  15. MvdS Says:

    I don’t know an easy fix for floats (unlike integers). In the last comment, replace nint() by floor().

    • drj11 Says:

      Try -2.1. FLOOR indeed. Do I have to debug everone’s Fortran? I don’t even know the language. It’s going on my CV at this rate.

      • dib Says:

        Why not use int(), i.e.

        t = 3.14159
        write(*,’(F8.2,TL8,I5.5)’) t, int(t)

        This should work with numbers of both sign as int() truncates towards zero.

  16. drj11 Says:

    @dib. Ah, very cunning. It so happens that I do not have access to a Fortran compiler right now. So perhaps you can be a good chap and test if it works with t = 1.997.

    Thanks.


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: