hexagon logo

PCL; is there a string formatting which can produce 8 digits Nastran exponentials?

PCL; is there a string formatting which can produce 8 digits Nastran exponentials?
  • There is no inbuilt function that does exactly what you want.
    The translator codes for writing the nastran input files would be written in Fortran or C etc and will be implementing this in their native code. It is a seemingly simple but in practice quite involved exercise to get the most accuracy into a Nastran 8 digit real string from a real number of arbitrary magnitude. The challenge is to change the format conversion depending on the magnitude and also to account for rounding.
    The following function will give you an idea how you might do this in PCL though performance may be poor.
    The example does not extract the maximum accuracy for small numbers like -0.098765 which will come out as -0.09877 when the most accurate for NASTRAN is -.098765 , to get this accuracy requires doing the real to string conversion with another digit of accuracy and then trimming the leading 0 from the resultant string, but leaving any negative sign in place.
    Also remember that for small numbers with negative exponential data it is possible to change format like "-0.1234E-5" to "-.1234-5" which gains 2 more digits compared with truncating the number as "-0.12E-5", again this example code does not do this.
    Hopefully the example will help but working with the wide field 16 digits is of course much easier and more accurate though people do like the 8 character wide fields despite their lack of significant digits.
     
    FUNCTION r2nas(invalue)
      REAL value
      REAL absval
      REAL invalue
      STRING sval[8]
      INTEGER sdig
      INTEGER digbefore
      INTEGER digaft
       
      value = invalue
      absval=abs(value)
      digaft=1
       
      sdig = 0
      IF (value < 0.) then
        sdig =-1
      END IF
       
      IF ( absval < .99999995e-9 ) then  
        sdig += 3
        digbefore = 1
      ELSE IF ( absval < .0099999995) then
        sdig += 4   
        digaft=2
        digbefore = 1
      ELSE IF ( absval < .099999995) then
        sdig += 5 
        digaft = 2
        digbefore = 1
      ELSE IF ( absval < 0.99999995) then
        sdig += 6  
        digbefore = 1
      ELSE IF ( absval < 999999.95) then
        sdig += 7
        digbefore = sdig - 1
      ELSE IF ( absval < 9999999500.) then
        sdig += 5
        digbefore = sdig - 1
      ELSE 
        sdig += 4
        digbefore = sdig - 1  
      END IF
       
      str_from_real_signif_digit(value, sdig, digbefore, digaft, 0, sval)
       
      RETURN sval
    END FUNCTION
     
     
  • Here is my second thoughts on doing this - just posting so that both ideas are in the same discussion.
    FUNCTION r2nas8(invalue)
      REAL value(1)
      REAL invalue
      REAL logval
      REAL absval
      STRING sval[18]
      STRING retstring[8]
      INTEGER sdig
      INTEGER ints(1)
      INTEGER i10
      INTEGER status
      STRING fmtstr[50]
       
      value(1) = invalue
      absval = abs(value(1))
      IF ( absval == 0.0) THEN return "  0.0 "
      logval = log(abs(value(1)))
      i10 = logval
        
      sdig = 0
      IF (value(1) < 0.) then
        sdig =-1
      END IF
       
      IF ( i10 <= -9 ) then
        sdig += 3
        fmtstr="%E8."//str_from_integer(sdig)//"C%"
      ELSE IF ( i10 <= -1) then
        sdig += 4
        fmtstr="%E8."//str_from_integer(sdig)//"C%"
      ELSE IF ( i10 < 6) then
        sdig += 6 - i10
        fmtstr="%F8."//str_from_integer(sdig)//"C%"
      ELSE IF ( i10 < 10) then
        sdig += 4
        fmtstr="%E8."//str_from_integer(sdig)//"C%"
      ELSE
         sdig += 3
        fmtstr="%E8."//str_from_integer(sdig)//"C%"  
      ENDIF
       
      status = string_write(fmtstr, ints, value, "", sval) 
     
      IF ( status > 0 ) THEN RETURN "CnvERROR"
       
      retstring=sval
      RETURN retstring
    END FUNCTION