forums.silverfrost.com Forum Index forums.silverfrost.com
Welcome to the Silverfrost forums
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Converting REAL number to character string in FTN95?
Goto page Previous  1, 2
 
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Support
View previous topic :: View next topic  
Author Message
Sebastian



Joined: 20 Feb 2008
Posts: 177

PostPosted: Thu Sep 09, 2010 7:10 am    Post subject: Reply with quote

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
View user's profile Send private message
JohnHorspool



Joined: 26 Sep 2005
Posts: 270
Location: Gloucestershire UK

PostPosted: Thu Sep 09, 2010 8:05 am    Post subject: Reply with quote

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
View user's profile Send private message Visit poster's website
LitusSaxonicum



Joined: 23 Aug 2005
Posts: 2428
Location: Yateley, Hants, UK

PostPosted: Sat Sep 11, 2010 2:27 am    Post subject: Reply with quote

Internal WRITEs are fast. In the Fortran-66 days, WRITEs were slow, but that wasn’t a code issue – it was due to the mechanical slowness of first line printers (or card or tape punches), then magnetic tapes.

You don’t 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
View user's profile Send private message
JohnCampbell



Joined: 16 Feb 2006
Posts: 2625
Location: Sydney

PostPosted: Sat Sep 11, 2010 3:49 am    Post subject: Reply with quote

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
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    forums.silverfrost.com Forum Index -> Support All times are GMT + 1 Hour
Goto page Previous  1, 2
Page 2 of 2

 
Jump to:  
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