sorry,
I try to write a file.dat whit a lot of columns (11) with different format (1.4e-12, 10...)
when i try ro write the code i use the following fortran command:
WRITE(7,*) id,t,a,e,inc,capom,omega,capm,mass,radius
but each line in the original file is now write in multiply lines.
From:
1222221 0.0 10.0 0.0 3.1415927 0.0 0.0 3.7828348 9.0E-9 4.0E-6
to:
1222221 0.000000000000000E+000 10.0000000000000
0.000000000000000E+000 0.000000000000000E+000 0.000000000000000E+000
0.000000000000000E+000 1.67102026939392 9.000000189551827E-010
3.999999989900971E-006
How can i resolve this?
Thanks a lot for your help!
You need to specify the format you want. You can do this by using
i0 to specify some unknown width integer
f4.1 to specify an up-to 2 digit real plus 1 decimal place (min of 0.0 and max of 99.9)
f9.7 to specify an up-to 1 digit real plut 7 decimal places (fits pi nicely there)
es10.1 to specify an up-to 8 digit scientific notation real with a single decimal place (will fit 9e-9 nicely)
1x to specify a space between each number
These can be used together to get
write(7,'(i0,1x,3(f4.1,1x),f9.7,1x,2(f4.1,1x),2(es10.1,1x))') &
id,t,a,e,inc,capom,omega,capm,mass,radius
Related
I'm learning Fortran and found some strange things when writing with a format (I'm using Fortran onlinegdb)
Program Hello
real, dimension(3,2):: array
array = 0
write(*, '(A,/, A,/, F5.2, F5.2)') &
"1","2",((array(i, j), i = 1,3), j = 1,2)
End Program Hello
I expected
1
2
0.00 0.00
0.00 0.00
0.00 0.00
I get
1
2
0.00 0.00
0.00 0.00
What's wrong?
Vladimir F is correct in saying that the format given does not suit the items that are provided for output: with format reversion after writing two real values, the control goes back to looking at the edit descriptor A but what corresponds to that isn't another character variable. This is not allowed.
However, the format suggested in an earlier revision of that other answer also does not give the output that you expect. If you want to write pairs of numbers on each line relying on an unlimited repeat specification, you'll need to explicitly put the file positioning into the format:
write(*, '(2(A,/),*(2F5.2,:,/))') "1", "2", transpose(array)
Without the / edit in there at the end, the repeat will mean that all elements of the array go in the same record. We also have : there, so that we don't get an extra line break after the final array element.
(I've also transposed the output array, as that's probably what you really mean. The implied do loop in the original output is a little unexpected and makes more sense moving over the final index first.)
With a limited repeat specification, as shown in the corrected form of that answer, format reversion does imply positioning:
write(*, '(2(A,/), 2(F5.2))') "1","2", transpose(array)
After processing the 2(F5.2) reversion has this reused while there are still elements to write out.
In summary, if you are relying on format reversion to "skip" earlier parts of a format while keeping new records, you must correctly mark the part of the whole format to revert to using parentheses. With just the whole format surrounded by parentheses, and no others, format reversion reuses the whole format.
You requested two strings to be printed, each on a new line, then two floating point numbers. That happened correctly.
But then there were still remaining items in the array. The format interpretation started again from the beginning with a new line and again for two strings and two numbers. But the array did not contain any strings...
Try '(A,/, A,/, (F5.2, F5.2))' instead. That will repeat the two-times floating point number format group until there are still numbers to be processed but this time the format does not return to the very beginning. (Note: the old and untested revision of the answer featured an extra repeat count - I did not realize this will disable the format reversion.)
When I code in Fortran language, I find when I set REAL value as control-var in do-loop, the outputs are strange, for example:
do i=0.1,1.0,0.1
write (13,"(F15.6)") i
end do
The out puts are: 0.1,0.2,0.3,0.4,0.5,0.6,0.7,0.8,0.9,1.0.But when I set the start value as 0.6:
do i=0.6,1.0,0.1
write (13,"(F15.6)") i
end do
the outputs are:0.6,0.7,0.8,0.9,and 1.0 is not outputted. Why does this happen?
This is basically a rounding issue see Precision problems of real numbers in Fortran and the link that follows from there. Comparing two floating points is tricky and it does not play well with do loops.
You should print more decimal numbers and not just 6:
0.1000000015
0.2000000030
0.3000000119
0.4000000060
0.5000000000
0.6000000238
0.7000000477
0.8000000715
0.9000000954
1.0000001192
The values are not precise.
In Fortran the number of iterations is computed before starting the loop. And when you compute the loop trip count:
write (*,"(F15.10)") (1.0 - 0.1) / 0.1
write (*,"(F15.10)") (1.0 - 0.6) / 0.1
you will get:
9.0000000000
3.9999997616
so the latter one will be iterated only four times (3 + 1 = 4; so i = 0.6, 0.7, 0.8 and 0.9), because the count is truncated from 3.999... to 3.
Real loop counters were deleted from Fortran for good reasons, don't use them. The rounding is one of the problems. The compiler should warn you:
Warning: Deleted feature: Start expression in DO loop at (1) must be
integer
Also, naming a real variable as i should be a crime.
I am trying to read a list of real numbers from an external file into an array. I do not know how many records fields, separated by spaces, there are per record in a file, and I was therefore planning to use non-advancing I/O to first count the number of records fields, then allocate a real array of sufficient size, and to finally read the file into that same array.
Here is an example input file (where the edit descriptor should be f3.1 for every record field, i.e. a float 3 characters wide with one decimal, and counting the dot; although if I read Metcalf et al. correctly, the decimal is ignored):
1.0 2.0 3.0 4.0 5.0
And a MWE of my program looks like this
program testread
use iso_fortran_env
implicit none
character(len=255) :: filename
filename = 'read.dat'
print *, count_entries(filename)
contains
integer function count_entries(coefficient_file) result(n)
character(len=*), intent(in) :: coefficient_file
!real, dimension(:), allocatable :: coefficients
integer :: fileunit, stat
real :: temp
n=0
open(newunit=fileunit, file=coefficient_file, iostat=stat)
do
read(fileunit,'(f3.1)',advance='no',iostat=stat) temp
if (stat == iostat_end) then
exit
else
n = n + 1
end if
print *, stat, temp
end do
close(fileunit)
! What should happen in the future...
!allocate(coefficients(n))
!read(fileunit,*,iostat=stat) coefficients
end function count_entries
end program testread
If you save the sample input above as read.dat, compile the program with gfortran -o testread{,.f90} and execute it, you will get the following result:
0 1.00000000
0 2.00000000
0 0.300000012
0 0.00000000
0 4.00000000
0 5.00000000
-2 0.00000000
7
In other words, instead of counting 5 entries, it counts 7. And this is not surprising as it, for some reason, sees 7 numbers. But I wonder: why does it see 7 numbers? How can I extend my function to a) be able to also read larger reals and b) read reals of non-uniform width? For example, I would like to be able to read 1.01 1.003 2.1, etc.
It sees six numbers (the last one is an end of record condition) because your format specification specifies that three characters be read each time, but your data is spaced every four columns (three for the data, one for the separating blank).
If your input isn't fixed format (number of columns may vary), then read the whole record (line) into a character(:), allocatable variable and then manually chop that string up.
(Never use a format specification with a specified number of decimal places for input unless you know that your input will always suit that.)
You forgot to account for the spaces. Just use '(f3.1,1x)'.
have declared a variable:
real*4 FACTOR
and then FACTOR=2.25
I want to output 2.25
Tried F3.2
Any help?
WRITE (lu09,9315)FACTOR
9315 FORMAT (F4.2)
The Fortran format F3.2 would output numbers up to .99, but anything larger won't fit. If you mean you want 3 digits before the decimal, change it to F6.2.
The first format number is the total field width, including the decimal and fractional digits.
For 2.25 to appear, the format width must be at least 4: F4.2
The f0.2 format gives the desired output, as demonstrated below. It writes the number with two digits after the decimal point and as many digits before the decimal point as needed.
program xwrite
implicit none
real*4 :: factor = 2.25
write (*,"(f0.2)") factor
end program xwrite
! output:
! 2.25
This should be quite simple, but I can't manage to read in a floating point number in Fortran. My program test.f looks like this:
PROGRAM TEST
open(UNIT=1,FILE='test.inp')
read(1,'(f3.0)')line
STOP
END
The input file test.inp simply contains a single float: 1.2
Now the compiling of my testfile goes fine, but when I run it I get an error:
At line 4 of file test.f (unit = 1, file = 'test.inp')
Fortran runtime error: Expected REAL for item 1 in formatted transfer, got INTEGER
(f3.0)
^
I've tried different modifications of the code and also googling for the error message, but with no result. Any help would be greatly appreciated!
Regards,
Frank
Your variable line is implicitly defined as integer. This doesn't work with thef edit descriptor. If you want to read an integer use i edit descriptor (i3 for example). Otherwise declare line as real to math the "f" descriptor.
Note beside: the .0 is not a problem, because if Fortran gets a number with decimal point the .0 part in the descriptor is ignored. It is only used when an number without a decimal is entered and then it uses the number behind the decimal point in the desciptor to add a decimal point into the right place. For with F8.5, 123456789 is read as 123.45678. More ont this here http://software.intel.com/sites/products/documentation/hpc/compilerpro/en-us/fortran/lin/compiler_f/lref_for/source_files/pghredf.htm .
In your read statement
read(1,'(f3.0)')line
the f3.0 tells tour program to read 3 digits with 0 digits after the decimal (this is what the n.m syntax means). So I presume that the program is just reading 1 from the file (not 1.2), which is an integer. Try replacing that line with something like
read(1,'(f3.1)')line
although, if the number in your file is likely to change and be larger than 9.9 or have more than one decimal place you should increase the field width to something larger than 3.
See the documentation of the read intrinsic and for data edit descriptors for more information on reading and writing in Fortran.
Edit: the format specifier, the second argument in quotes in your read statment, has the form fw.d, where f indicates that the data to read is a floating point number, w is the width of the field including all blanks and decimal points and d specifies the number of digits to the right of the decimal point.
I would suggest reading/writing list formatted data, unless you have a very strong reason to do otherwise. assuming that you're reading in from a file with just a single float or integer in a single line, like this
123.45
11
42
then this should do the reading
real*8 :: x,y,z
open(1,file=filename)
read(1,*)x
read(1,*)y
read(1,*)z
close(1)