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.

16 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.


Leave a Reply