When reading data from an ascii file, I have this error : Program received signal SIGFPE: Floating-point exception - erroneous arithmetic operation
This error occurs when reading the value 6.969d-39 from the text file. When I change that value to 6.969d-09, the error disappears. This error happens with a variable being of type REAL64 or REAL128. I am quite surprised because I assumed that 1e-39 is well within the limits of REAL64. I am reading that value with free format : fmt=*.
When writing the minimal example below quite the same way as in my project, the error does not occur for an ascii file with the value 6.969d-39 !
program read
use iso_fortran_env, only:REAL128
INTEGER, PARAMETER :: DBL = KIND(REAL128)
integer :: fUnit
real(DBL) :: val1,val2,val3
integer :: i
open(newunit=fUnit, file = 'temp.txt',action='read')
read(fUnit,*) i,val1,val2,val3
write(*,*) i,val1,val2,val3
close(fUnit)
end program read
the text file contains one line which is the same as in my project where the error occurs: 2 6.969d-39 0.5 0
The sample runs fine either with my ubuntu 22.04 with gfortran-10 (with -g option). I simply do not succeed in having a minimal example producing the same error. For that minimal code, I just put the same read line, the exact same kind of variable on the same line of file, so the reading context is more or less the same as in my real-life project.
In my real project (to big to show there), what is weird is that by changing the exponential part of the floating point number from d-39 to d-09, my projects switches from not running to running fine.
Thanx
I suspect the issue is in the way you define the kind of the real variables.
What you mean is different from what you coded. real32/64/128 from iso_fortran_env intrinsic module are already real kinds parameters.
If you take their kind, you are actually querying the kind of the underlying integer used to define them.
program test
use iso_fortran_env
implicit none
integer, parameter :: DBL = kind(real128)
real(DBL) :: not_a_r128
real(real128) :: r_128
print *, kind(not_a_r128)
print *, kind(r_128)
end program test
you are right. How stupid I am ! It is a pity that the compiler get it through … The blame is also on me because I did not pay enough attention to a few warnings in visualstudio code indicating the use of real(4)
Thank you but I am sorry for the time you spent for that. I will use the -Wall option and make all the fix required from now on!
Regarding using real(real128), I took the DBL idea from “chapman’s fortran for scientists and engineers”. It has the advantage that if I want to switch from real128 to real64, I just have to change it at a single file at a single location without introducing possible mistakes. Anyway, you are right, it is less expressive.
Then, I would have used a different kind parameter name, something like RK (real kind), to express the fact that reals declared as real(RK) might be of any desired kind.
By itself, DBL closely recalls the intrinsic double precision, which is directly linked to the default kind of simple real variables.
But yeah, finally choose a name that you are comfortable with.
Well, @vmagnin, it is the demonstration that I am even more stupid than I thought, since I’m doing what you are suggesting, for stdout => output_unit … I should I think of your nice proposal by myself !
A programmer would do this when he wants to hide REAL128 (and the other REAL* parameters too). If the programmer wants to have those parameters available, and also define a local RK, then a parameter definition is appropriate.
Here is a run on mint linux. i saved the program s an f.08 file.
ian@ian-Latitude-E7440:~$ nano temp.txt
ian@ian-Latitude-E7440:~$ ./a.out
2 6.96900058E-39 0.500000000 0.00000000
ian@ian-Latitude-E7440:~$ cat temp.txt
2 6.969d-39 0.5 0
ian@ian-Latitude-E7440:~$ cat testx.f08
program read
use iso_fortran_env, only:REAL128
INTEGER, PARAMETER :: DBL = KIND(REAL128)
integer :: fUnit
real(DBL) :: val1,val2,val3
integer :: i
open(newunit=fUnit, file = 'temp.txt',action='read')
read(fUnit,*) i,val1,val2,val3
write(*,*) i,val1,val2,val3
close(fUnit)
end program read
ian@ian-Latitude-E7440:~$
Your version of the test program is also deceptive. The variables val1, val2, val3 are single precision, despite being declared to have the kind DBL. To see that, add the following PRINT statement and run:
My compiler (gfortran10) tells me when i try to compile read(fUnit,“(i,3f)”) i,val1,val2,val3 : Nonnegative width required in format string at (1) (1) referring to i.
So I am using free format… May be I do something wrong once again !
Yes, that format is nonsense. Maybe it was corrupted by the display formatting. If you want to avoid using list-directed i/o, you can also experiment with the g format field. Here is a small example:
program g
integer :: i = -99
real :: val(3) = [1.0, -10., 1000.0]
write(*,*) i, val
write(*,'(*(g0,1x))') i, val
write(*,'(*(g0.2,1x))') i, val
end program g
$ gfortran g.f90 && a.out
-99 1.00000000 -10.0000000 1000.00000
-99 1.00000000 -10.0000000 1000.00000
-99 1.0 -10. 0.10E+4
Silly me! I forgot you have to give it the number of characters on input. My fault! So given what you are reading, you might not be able to dictate those numbers!.. Ouch…
I also didn’t notice that 6.969d-39 doesn’t look right… Isn’t that supposed to be 6.969e-39?..