WRITE format that permits variable numbers of decimal places

WRITE format that permits variable numbers of decimal places

Hi folks

I can't seem to find anything on this issue, which kind of surprises me... I've looked around pretty thoroughly though.

I'd simply like to write to a file with a format that specifies the number of characters in the number, and the minimum number of dps. For instance, I need to write a line with two integers (2I5) followed by 6 reals (currently 6F8.4). The reals range from 1.something to 100.something so while this format permits the latter case the maximum number of dps it also limits the smaller numbers to only four dps, when more could clearly fit. I know we have some flexibility in this when dealing with reads, but things seem very rigid when it comes to writes and I can figure out no workaround.

I cannot just use list-directed because that uses up too many spaces per write and I can figure out no way to control that without using formatting, which gets me back to the original issue.

Any suggestions would be much appreciated.

21 posts / 0 new
Last post
For more complete information about compiler optimizations, see our Optimization Notice.

Look at the description of the G format item - it is close to what you want. What I think you REALLY want is the G0.d format from Fortran 2008. We expect to support this in the next major release.

Retired 12/31/2016

An alternative would be to use code like this:

character(len=1000) :: string

character(len=20) :: number

string = ' '

do i = 1,size(array)

write( number, '(f10.4)' ) array(i)

string = trim(string) // ' ' // triml(number)

enddo

(Not very efficient, I admit, because of the string length of the variable string, but that was easier than mucking about with a substring)

Regards,

Arjen

Make that:

string = trim(string) // ' ' // adjustl(number)

Regards,

Arjen

What I would like to see is a "significant figures" format where you specify the field width and the number is written such that is uses the best format to display the most significant figures while taking into account the sign, decimal point and any exponent format requirements. Is this what G0.d will do?

Currently I have a routine to do this but it slows down the writing process as it uses the log function and lots of string manipulation just to write outthe number how I need it. We need to retain as much accuracy as possible when creating data files for third party programs that require fixed size (8 character) fields for input and numbers can range between -xxxxx.x to xxxxx.x floating point. I also remove the E from exponent as well as any superfluous zeros.

eg

1.23456E+09 would become 1.2346+9 (This is accepted by the program reading the data files)

-1.100000 would become -1.1

and so on.

If you are concerned about getting the most significant figures in 8 characters, then 0.1234-3 has 4 significant figures, 1.2345-4 has 5 significant figures, but 123456-9 has 6 significant figures, as does 123456+9.So You do(may) not need the decimal point if you use the exponent form.

Consider 99999999. This can be written 999999+2 and loses2 significant figures producing 99999900 when converted.

1234.567 uses all 8 characters,and has7 sig figs, but 123456-2 loses a sig. fig.

It is asking a lot of a simple format control to produce the following:

number sig figs

99999+10 5
999999+9 6
999999+8 6
999999+7 6
999999+6 6
999999+5 6
999999+4 6
999999+3 6
99999999 8
999999.9 7
99999.99 7
9999.999 7
999.9999 7
99.99999 7
9.999999 7
.9999999 7} same number
999999-6 6}
999999-7 6
999999-8 6
999999-9 6
99999-10 5

Unfortunately the G format doesn't work for me because it seems to add exponent formatting in some cases, which blows the length of my output beyond the specified 8 characters (or forces me to reduce the number of dps) and as Anthony just pointed out, steals my sigfigs.

I am writing a LOT of output so I'm not sure how efficient your string manipulations will be Arjen, but I have used that solution for some smaller edits and it worked great - thanks!

I'm still rather new to Fortran in the grand scheme of things, but I have to admit to being surprised that such a computationally explicit and potent language does not allow you to more simply control the number of significant figures when writing to output.

I hope that G0.d is, indeed, exactly what I am looking for. And that I still need it by then ;-)

Thanks again everyone

G format does allow you to specify the number of significant digits. What it doesn't do is provide it with the minimum number of characters - that's what G0 does. And G0.d gives you minimum characters and a specified number of digits.

Retired 12/31/2016

So it seems what we're missing is the ability to specify the number of significant digits as the number of specified characters, which would ensure that the allocated character field is fully utilized, but without having to specify anything about the number of dps. This latter consideration is important because specifying the number of dps when the order of the whole number may vary can push the printed output beyond the character limits for large numbers, or inhibit full use of the space for small numbers.

E is a great way of controlling the sigfigs in this way but the notation requires allocating character space to the exponent term, which in turn effectively uses up potential sigfigs in the print.

Again, this is only really an issue when the output print is limited for some reason to a particular number of characters spaces. If that limitation is removed then one can simply use E format and print to the desired number of sigfigs, including additional character space to account for the exponent term.

Does that about sum it up?

Can you give some examples of what you'd like to see?

Retired 12/31/2016

Lets call the format Mc.s, where M is for Magical format, c is the number of character spaces allocated for the print, and s is the number of significant figures.

Say I need to print the 6 REAL*8 numbers stored in VECTOR(6), with a maximum number of 8 characters spaces available for printing each number. The maximum value in VECTOR is 100.123456789etc, while the minimum is 1.123456789etc

WRITE(UNIT, '(6M8.7)') (VECTOR(i),i=1,6) would then produce the following (I've artificially added a spaces between each print to make the numbers clear)

100.1234 10.12345 1.123456 etc

It would be nice if the format could automatically adjust to print to exponential notation if that is necessary to maintain the maximum possible number of significant figures (in which case "s" would be the maximum number of sigfigs, not the enforced number of sigfigs). For example, if the minimum value were 0.0000123456789etc, then if printed without an exponent it would be 0.000012, which only has 2 sigfigs, compared with 1.234E-5, which is has 4 sigfisg - it's not 7, but it's better than 2, and it's the optimal number achievable with only 8 character spaces to print in (I guess it could also be printed 1.2345-5, which sneaks in an additional sigfig).

I posted some code for a function to do this, in comp.lang.fortran some years ago. Here is the link to it in google groups:

http://groups.google.com/group/comp.lang.fortran/browse_thread/thread/975120126af71895/e54cc49eed61b1bd?lnk=gst&q=significant+figures+colin+watters#e54cc49eed61b1bd

...As the posting says, "efficient, it is not!". But it works for me, in the absense of anything in the compiler that can do better. So maybe it'll give Steve and his crew the idea of what is wanted for a native format descriptor. In fact I suspect the G0.d will do this.

I think that Gw.d, available now, is very close. You may want to write the value to a string and then do a TRIM on the value. The advantage of G0 is that the value takes the minimum possible width automatically.

Retired 12/31/2016

Well, I guess our ideas of what constitutes "very close" must differ somewhat.Try using any Gw.d format to write the value in CVAL back out in only 8 characters:

program demo
implicit none

character*8 cval
real(8) val

cval = '.12345e-6'
read(cval,'(f8.0)') val

write(*,'(g8.5)') val
continue

end

I'd be VERY interested to see what a G0 could do with this.

Ok so I can't count (I'm just a programmer after all), try doing it in 9 characters, and increase cval's length to match.

G0.5 gives you "0.12345E-06" What do you want to see?

Retired 12/31/2016

How would this example deal with one more significant figure? Would it utilise the digit before the decimal point? One of the issues I've raised in the past is that the G format does not allow the additional control available in the E format whereby you can specify EN (or ES to form the scientific notation).

i.e. GN could be used to format all numbers requiringexponent notation to use the first digit. (Could this be put into the G0.d (if it is not already covered)?

Another enhancement would be to be able to omit the E and any unecessary exponent zeroesaltogether from the output string. This would free up two additional spaces for numbers in the range -9.999e09 to 9.999e09.

For values in the range where the exponent is used, there is always a leading zero (unless P is used). You can't use the En suffix to control the number of exponent digits with G0 or G0.d. The EN and ES format behavior is not available.

The G0.d behavior is fixed by the Fortran 2008 standard (draft). It's not going to change. However, if one used 1PG0.5, you get "1.23450E-07"

You can say something like 1PG11.5 today and get " 1.23450E-7". Note that the 1P doesn't change the behavior if the value is in the "F format" range.

Retired 12/31/2016

I'd like to see ".12345E-6", or "1.2345-7", or similar.

I'd like to be able to specify the total field width in characters, and have the edit descriptor fill it with as many significant figures as possible, along with the exponent and signs if necessarry, but WITHOUT unnecessarry leading zeros. I believe this is very similar to what stubban (the OP) wants as well (correct me if not, stubban).

Your result from using G0.5 is identical to what G11.5 will give us right now.

Thanks anyway...

No, G0.5 is not the same as G11.5. G0.5 will have no leading or trailing blanks, whereas G11.5 may.

Retired 12/31/2016

I was intrigued by this problem, so I have written the attached code to
demonstrate a method of restricting the format to a given character length and converting a floating point number to fill it whilst maximising the sig.figs.

The code takes the form of a subroutine that
lets you specify a floating point number and the number of characters to
be used to format the number and converts a floating point number to fit within that length,
returning a string of the required length, while maximising the number of sig.figs.
If digits are lost because of truncation to fit within the format, some rounding up is done first.
In the test program provided, the converted string is read back using a Fn.0 format in order
to regenerate the number so that it can be compared with the original. :-)

Attachments: 

AttachmentSize
Downloadapplication/octet-stream printg0.f909.68 KB

Leave a Comment

Please sign in to add a comment. Not a member? Join today