How to pad Fortran floating point output with leading zeros?

前端 未结 5 1094
执念已碎
执念已碎 2020-12-10 15:57

I have some floating point numbers that I need to output from a Fortran program. Let\'s say the maximum number could be 999.9999 and they are all non-negative. I need zero

相关标签:
5条回答
  • 2020-12-10 16:14

    I do not believe that there is an edit descriptor that does what you want, but you could simulate it with an if-statement:

    if(var < 10) then
       write(*,'(a,f6.4)') '00',var
    else if(var < 100) then
       write(*,'(a,f7.4)') '0',var
    else
       write(*,'(f8.4)') var
    endif
    
    0 讨论(0)
  • 2020-12-10 16:20

    An alternative method to the method of High Performance Mark is to do use the TL and TR position-edit-descriptors. First print the float with Fw.d, move w positions back, print the integer with padding zeros and width w − d, move d + 1 positions forward.

    write (*, '(F6.3,TL6,I2.2,TR4)') f,int(f)
    

    The problem this method and the method of High Performance Mark have is rounding. The following program demonstrates this:

    program test_rounding
      double precision :: f
      f = 6 - 1D-6
      ! default compiler dependent rounding :: gfortran NEAREST
      write (*, '(F6.3,TL6,I2.2,TR4)') f,int(f)
      write (*, '(I2.2,F0.3)') int(f), f-int(f)
      write (*, '(I2.2,F4.3)') int(f), f-int(f)
      ! rounding to ZERO
      write (*, '(I2.2,RZ,F4.3)') int(f), f-int(f)
      write (*, '(RZ,F6.3,TL6,I2.2,TR4)') f,int(f)
    end program
    
    05.000          < WRONG
    051.000         < VERY WRONG
    05****          < EUH
    05.999          < OFF BY 0.001
    05.999          < OFF BY 0.001
    

    The last method might be of interest, but it is not really the expected value. However, it has the same accuracy.

    The following two methods work as expected, but it is required to do manual manipulate the numbers with the respected accuracy. This is not what one would expect:

    program test_rounding
      double precision :: f
      f = 6 - 1D-6
      ! manual manipulation
      write (*,'(I2.2,".",I3.3)') nint(f*1D3)/1000, mod(nint(f*1D3),1000)
      write (*,'(F6.3,TL6,I2.2,TR4)') f,nint(f*1D3)/1000
    end program
    

    Both return 06.000

    0 讨论(0)
  • 2020-12-10 16:21

    This works for me

    real :: areal
    

    then

    write(*,'(i3.3,f0.6)') int(areal),areal-int(areal)
    
    0 讨论(0)
  • 2020-12-10 16:29

    Zero-padding can be performed for integer fields, so if you printed the result as two separate fields you might be able to make it happen. Here's a way that is less than pretty, but works. Say x is the value you want to print:

    DOUBLE PRECISION x
    CHARACTER*6 y
    
    x = 123.4567
    
    WRITE(y,'(F6.4)') x-int(x)
    
    
    WRITE(*,'(I3.3,A5)') int(x), y(2:5)
    

    y is declared as a CHARACTER*6 because it needs to hold the fractional part of your number (4 decimal places), a leading zero, and a decimal point. This can be easily changed if you want to show more decimal places, though it would be trickier if you wanted to show a variable number of decimal places.

    The I3.3 field descriptor means "print an integer with a maximum field width of 3 and pad left with zeroes so that there are always 3 digits". When printing out the value we take y(2:5) to strip off the leading zero.

    Happy coding!

    0 讨论(0)
  • 2020-12-10 16:30

    This is a trick I used to use in MS BASIC on the Commodore PETs in the late 70s. The code has been modified for negative numbers. If you would like positive numbers to have a leading +, just change the last character of signchr to '+'

    subroutine leadingzero(x)
       real x
       character(len=16) str
       character, dimension(3):: signchr = (/'-', ' ', ' ' /)
       write(str,'(F9.4)') 1000.0 + abs(x)
       write(*,*) signchr(int(sign(1.0,x)) + 2), str(2:) ! drop the 1
    end subroutine leadingzero
    
    program main
       call leadingzero(0.01)
       call leadingzero(0.1)
       call leadingzero(2.532)
       call leadingzero(9.9999)
       call leadingzero(9.999999)
       call leadingzero(10.987)
       call leadingzero(123.456)
       call leadingzero(0.0)
       call leadingzero(-0.01)
       call leadingzero(-0.1)
       call leadingzero(-2.532)
       call leadingzero(-9.9999)
       call leadingzero(-9.999999)
       call leadingzero(-10.987)
       call leadingzero(-123.456)
    end program
    

    Edit - returning result in a string

    subroutine leadingzerostr(x, str_temp)
        real x
        character(*) str_temp
        character(len=10) str
        character, dimension(3):: signchr = (/'-', ' ', ' ' /)
        write(str,'(F10.4)') 10000.0 + abs(x)
        str_temp = str
        str_temp(1:1) = signchr(int(sign(1.0,x)) + 2)
    end subroutine leadingzerostr
    
    0 讨论(0)
提交回复
热议问题