In the absence of a de facto common standard, and in the belief that needless spaces and zero digits donât contribute anything of value to the output, Iâm producing this from f18:
1 2 3. 4.
The floating-point values are in âminimalâ form â the fewest digits needed to recreate the same binary value after input into the same kind of REAL.
Sound good? Any objection?
(EDIT: Subclause 13.10.4 applies, paragraphs 4-6; Iâm reading it as if I can choose âwâ, âdâ, &c. for each value rather than using constant âwâ, âdâ, &c. for all values.)
What are you asking for here? Most of the time you will have not perfectly fitting floating point numbers. It is more likely you will have numbers like 4.000000001 depending how the internal binary representation of a real number converts to decimal representation after rounding as appropriate.
In the case of gfortran list directed we choose a width such that if you write out a value and read it back in, you will get the same internal binary representation as close as possible. We chose to use a fixed width which that fortran standard states is processor dependent.
If you want finer control, use formatted output, that is what it is for. You can use the g0 specifier for a bit more generalized output.
ie. print '(g0)', 42.0
I really do not understand what you want to do, so clarify some if possible. I tried this:
print â(*(1x,g0.1))â, 1, int(2,kind=selected_int_kind(10)), 3., 4.d0
end
While the compact form is, well, compact, a drawback is that you do not see the difference between single and double precision values. In that respect the last type of output combines compactness and type information.
To make things even more convoluted: I have used list-directed output to quickly print my data and relied on a representation of a constant width (for reals) to examine the values. Admitted, that was shear laziness.
Also: list-directed is meant for quick-and-dirty output, the precise formatting is expressively left to the discretion of the compiler developers. So the lack of a standard is exactly on purpose.
In response to @Arjen comment about type info, only the first 3 truly preserve the type information. One can see the kind of real by the number of digits, and the kind of integer by the amount of leading whitespace (granted thatâs harder to see). So if you want to preserve all type information, one of those is prefered.
I personally donât find preserving the type information to be particularly useful to users. As a user of some program I would consider the internal representations to be an implementation detail I shouldnât have to care about. Round trip preservation is usually important, so that should be supported (i.e. donât truncate or round). Your proposed format does just that (I assume), while being compact. Thatâs what I would prefer.
As a matter of style, I prefer not to leave the dangling decimal point. I think those should have one trailing zero to make the decimal point stand out more.
and I wouldnât mind one trailing zero for whole real numbers as Brad suggested:
1 2 3.0 4.0
For single precision reals, I think all whole numbers smaller than 2^{23} should be represented exactly without trailing zeros. Of course, only the trailing zeros can be safely omitted from the output.
Indeed, aligned output is nice. However, as a user knowing that list-directed output format is up to the compiler, I donât expect alignment, especially if the code is to be compiled with different compilers.
I see how both aligned and compact formats can be nice depending on what Iâm doing. So, currently I prefer compact output by default, and a --align-list-directed-output as a compiler flag.
@pmk, for all the differences in the five different compilers you tried, you will note the floating-point output is essentially all the same, 3.00000000 and 4.0000000000000000.
And you may or may not be surprised to know many of your users (and who are likely not here) will have the same expectations with floating-point list-directed output with f18. Thus user experience and consistency with expectations can be a factor for you. Luckily the standard gives you the freedom to chart your path.
FYI: There was a discussion on the Fortran newsbook site about this topic. As I remember it anyone writing larger amounts of information preferred the alignment where each type is given enough space to print *, huge(I). So Integer values in particular seem very ugly when just printing a few values. The very same format mentioned here seemed to be what everyone thought was easy enough to use as an alternative when you wanted compact output as I remember it, with the caveat that produces totally different output for complex values. Tied up at the moment but I can find it if you are not familiar with the site. I have a hard time remembering it right now but I actually thought a nice solution would be that PRINT *, wrote âcompactâ but that WRITE(*,*) wrote with fields wide enough for any value of that type (ie. in âcolumnâ mode). The standard is pretty flexible with what list-directed output produces. Now-adays (there was no great alternative before g0) I use â(*(g0,1x))â a lot, enough so I have a mini-module with a few pre-defined formats. So just writing
write(*,gen)a,b,c,string,i,j,k
gives me the compact format; but I like the (a,b) format for complex values and that doesnât produce that.
PS:
The module also defines some little functions so things like
write(*,gen)ERROR(),a,b,c
writes a prefix of âERROR:â in white on a red background on ANSI terminal emulators if output is not a TTY; which shows I like overkill.
PSS:
There were several discussions about the leading space that list-directed output always produces too.