 |
forums.silverfrost.com Welcome to the Silverfrost forums
|
| View previous topic :: View next topic |
| Author |
Message |
Sebastian
Joined: 20 Feb 2008 Posts: 177
|
Posted: Thu Sep 09, 2010 7:10 am Post subject: |
|
|
Trying to get the essence out of this: '(f6.2)' may be bad because 6 can't cope with 1000000 or 10000.12. If the programmer can pre-determine the range, he's fine. Pretty often he can't so he has to choose, possibly re-compiling if he's touching limits (or losing customers because the program just doesn't work).
Don't know how far a simple "write(string,*) float" would get you to this, excluding specifying a minimum precision etc. |
|
| Back to top |
|
 |
JohnHorspool
Joined: 26 Sep 2005 Posts: 270 Location: Gloucestershire UK
|
Posted: Thu Sep 09, 2010 8:05 am Post subject: |
|
|
I have used routines similar to the one below for many years.
| Code: |
SUBROUTINE FORMS(V,STRING)
CHARACTER*9 STRING,F(0:8)
DATA F /'(0PF12.0)','(0PF12.1)','(0PF12.2)',
* '(0PF12.3)','(0PF12.4)','(0PF12.5)',
* '(0PF12.6)','(1PE12.4)','(F9.0,3X)'/
Z=ABS(V)
IF ((Z.GT.0.0.AND.Z.LT.0.001).OR.Z.GE.1.0E8) THEN
K=7
ELSE IF (Z.LT.1.0E-6) THEN
K=8
ELSE IF (Z.LT.0.999995) THEN
K=6
ELSE IF (Z.LT.9.999995) THEN
K=5
ELSE IF (Z.LT.99.99995) THEN
K=4
ELSE IF (Z.LT.999.9995) THEN
K=3
ELSE IF (Z.LT.9999.995) THEN
K=2
ELSE IF (Z.LT.99999.95) THEN
K=1
ELSE
K=0
END IF
STRING=F(K)
RETURN
END |
|
|
| Back to top |
|
 |
LitusSaxonicum
Joined: 23 Aug 2005 Posts: 2428 Location: Yateley, Hants, UK
|
Posted: Sat Sep 11, 2010 2:27 am Post subject: |
|
|
Internal WRITEs are fast. In the Fortran-66 days, WRITEs were slow, but that wasnt a code issue it was due to the mechanical slowness of first line printers (or card or tape punches), then magnetic tapes.
You dont need a rigidly fixed format like F6.2, because in an internal write the format can be contained in a character variable, e.g. if you know n and m (in Fn.m) then
| Code: |
WRITE (STRING1,(F,I3,.,I3,) ) n, m
WRITE (STRING2, STRING1) x |
(Apologies if I haven't got the right number of apostrophes. I usually use both single and double quotes - permissible since Fortran 90 - for readability, and several trial before getting it right).
In order to avoid lots of IFs, you can use the LOG10 function although this only works for positive X, so
| Code: |
| N1 = LOG10 ( ABS (X) ) |
where N1 is the number of characters before the decimal point for a number >1.0.
You may need to add 1 for a negative sign (and if you want a + plus sign). N1 is at least 1 more even for numbers <1.0 if you want a leading zero.
To get n, you need to consider the desired number of decimal places, plus N1 + 1, where the extra 1 if for the decimal point.
(It is possible to write X with a big n, then remove leading blank characters, but I prefer LOG10).
There is a maximum meaningful n, due to the number of significant contained decimal digits of precision (7 in REAL*4 ?). This used to be a big problem with all the different formats in mainframes (16, 24, 30, 32, 36 and 60 bit words in my personal experience, plus all the complexities of DOUBLE PRECISION), but now all we need to consider are 32, 64 and 80 bit precisions (and not even the latter in .NET). There are also practical limits on what values of n and m are sensible before scientific notation is anyway a more sensible option (for an example, see what scientific calculators do!).
A general purpose floating point variant of CNUM would also need to error-handle undefined numbers and special cases like NaN.
Most applications have intrinsic limits on range and precision for variables that contain physical values. For example, no distance on the planet earth can be more than 40 000 000 metres (plus a tiny bit!) or be negative, hence 2 < =N1 < = 8. Moreover, if a millimetre accuracy is adequate, then we can probably fix m=3, and n therefore between 5 and 12. I am sure that other forum users have their own examples. It probably means that even though n and m can in principle be calculated, the programmer probably needs to have some control over what is actually selected, even if they do not need to choose, a priori, what n and m are.
CNUM is a lot easier than the floating point equivalent because the range for integers is small, and the precision absolute. |
|
| Back to top |
|
 |
JohnCampbell
Joined: 16 Feb 2006 Posts: 2625 Location: Sydney
|
Posted: Sat Sep 11, 2010 3:49 am Post subject: |
|
|
Since Fortran 90, using n=0 is a good alternative, such as fmt='(f0.2)' or fmt='(1x,f0.2)'.
There is also the G format, which I don't use.
I prefer to control the m else use the ES format.
If the number is very small I use ' 0. '
John |
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|