convert fortran real integer into an I8.8 integer

Posted on 2005-04-13
Last Modified: 2013-11-08
I am using fortran and in my program I am reading a .CSV file which cuts off leading and trailing zeros. I need to turn the number with 2 decimal places into an I8.8 integer?
Question by:kphillips1
    LVL 32

    Expert Comment

    Can you please explain a bit more. What is an I8.8 integer?
    Also, by "number with 2 decimal places", provide an example. Do you mean a number wityh 2 digits (e.g. 37) or do you mean a number with a fractional component, like 37.02 ?
    LVL 2

    Expert Comment

      I don't quite follow your description. Presumably you have a disc file with a large amount of text, containing numbers separated by commas, thusly:
       Why should this format "cut off leading and trailing zeros"? Is your programme reading such files, or producing them?
       Using fortran, you could read such data using the free format option, thus:
          READ(IN,*) ARRAY
    where ARRAY is indeed an array, of some size or other. If ARRAY is a floating-point type variable, then all numbers, integer or not, will be suitable for input. The main problem is, how many numbers are to be read in? Each line of input has the same count of numbers, or, some count that is knowable? Or, is perhaps the first number the count of numbers to follow? In this (useful and flexible case) case,
          READ (IN,*) N,(A(I),I = 1,N)
       would do the trick.
       What do you mean by I8.8? That is not a valid format code. Do you mean F8.8? Or what? If something has decimal places, it is not an integer. If you wish, you could rescale the numbers: read them into ARRAY as floating-point (with any fractional parts acceptable, then transfer the numbers to an integer array, thus:
          IARRAY = ARRAY*100
       or, if N were known to have been read,
          IARRAY(1:N) = ARRAY(1:N)*100

       Amusingly enough, I have been confronting .csv data, and the following code segment might help. Following an EATINT is EATREAL, as follows:

          LOGICAL FUNCTION EATREAL(V)      !This is even worse.[than EATINT]
    Chews into the likes of 666, -666.666, and 666.666E666 (=666.666*10**666)
    Completes with the value in V, success as the result, and L1 and L2 advanced.
    Concocted by R.N.McLwean (whom God preserve) May XXMM.
           REAL*8 V,X,POW,TENS      !Maximum precision for all this fun.
           INTEGER*2 D,DD,P            !Digit counting and such.
           LOGICAL ADIGIT,XNEG,PNEG      !Things noticed along the way.
           REAL*8 TEN(0:8)            !A small table, only.
           DATA TEN/1,10,100,1000,10000,100000,1000000,10000000,100000000/      !Whee!
           CHARACTER*30 BURP      !In case of trace.
           INTEGER*2 I Am            !Self-identification.
            CALL $SUBIN("EatReal",I Am)      !Hello there.
            ADIGIT = .FALSE.      !No digits seen.
            PNEG = .FALSE.            !No negative exponent.
            XNEG = .FALSE.            !No negative number.
            DD = 0                  !No decimal digits.
            P = 0                  !No exponent.
            X = 0                  !No value.
            L2 = L1                  !The starting point.
            IF (L2.GT.LA) GO TO 40      !Urk! Off the end even before I start.
    Chew into the number. Admit a possible leading sign, then digits.
            IF (ACARD(L2:L2).EQ."+") GO TO 1      !Well, first consider
            IF (ACARD(L2:L2).NE."-") GO TO 2      !Possible signs.
            XNEG = .TRUE.                  !To be acted upon later.
        1   L2 = L2 + 1                  !Advance one.
        2   IF (L2 .GT. LA) GO TO 30      !Off the end?
            D = ICHAR(ACARD(L2:L2)) - ICHAR("0")      !Taste the candidate digit.
            IF (D < 0 .OR. 9 < D) GO TO 10      !Is it to my taste?
            X = X*10 + D            !Yes. Yum.
            ADIGIT = .TRUE.            !A digit has been seen.
            GO TO 1                  !More might well follow.
    Consider any decimal digits, those following a .
       10   IF (ACARD(L2:L2).NE.".") GO TO 20      !Any sign?
       11   L2 = L2 + 1            !Yes. Advance one.
            IF (L2.GT.LA) GO TO 30      !Sudden end?
            D = ICHAR(ACARD(L2:L2)) - ICHAR("0")      !Taste the digit candidate.
            IF (D < 0 .OR. 9 < D) GO TO 20      !Suitable?
            X = X*10 + D            !Yes. Accept as before.
            DD = DD + 1            !But now, count the decimal digits.
            ADIGIT = .TRUE.            !There may have been none before the decimal point.
            GO TO 11            !Carry on.
    Consider any exponent part, following an "E" or "D", etc..
       20   IF (INDEX("EeDd",ACARD(L2:L2)).LE.0) GO TO 30      !Any sign?
            L2 = L2 + 1            !Step past it.
            IF (L2.GT.LA) GO TO 30      !Sudden stop?
            IF (ACARD(L2:L2).EQ."+") GO TO 21      !A (redundant) plus sign?
            IF (ACARD(L2:L2).NE."-") GO TO 22      !A - sign to notice?
            PNEG = .TRUE.            !Yes. Noticed.
       21   L2 = L2 + 1            !Advance one.
            IF (L2.GT.LA) GO TO 30      !As ever, after every advance, fear the brink.
       22   D = ICHAR(ACARD(L2:L2)) - ICHAR("0")      !Check for a digit.
            IF (D < 0 .OR. 9 < D) GO TO 30      !It is one?
            P = P*10 + D            !Yes. Build up the power part.
            GO TO 21            !And look some more.
    Combine the components into one number then correct the power of ten.
       30   IF (XNEG) X = -X      !Correct the sign of the number.
            IF (PNEG) P = -P      !Correct the sign of any exponent.
            P = P - DD                !Now adjust the power of ten for decimal digits.
            IF (P .EQ. 0) GO TO 40      !No net fiddle! Yay!
            D = ABS(P)            !Oh well. Some power is required.
            POW = TEN(MOD(D,8))      !Gnash the bothersome low-order bits in one go.
            D = D/8                  !Now for the higher-order bits beyond the scope of my table.
            IF (D.LE.0) GO TO 32      !Are there any worthy of my regard?
            TENS = TEN(8)              !Yes! Prepare to acknowledge them.
       31   IF (MOD(D,2) .EQ. 1) POW = POW*TENS      !Bite this bit?
            D = D/2                  !So much for that level.
            IF (D .EQ. 0) GO TO 32      !Are we there yet?
            TENS = TENS*TENS      !No. Crank up another level,
            GO TO 31             !And keep trying.
       32   IF (P .GT. 0) THEN      !Because 0.1 = Binary .0001100110011001100110011001100....
              X = X*POW            !It is not represented in base two.
             ELSE                  !So *10 etc. is accurate,
              X = X/POW            !As is /10, etc.
            END IF                  !But *0.1 is inaccurate.
    Complete the action.
       40   V = X                  !The result at last.
            IF (TRACE%EATREAL) THEN      !Are we under inspection?
              WRITE (BURP(3:),*) X      !Alright, reveal what was found.
              BURP(1:2) = "v="      !Squeeze in a prefix.
              CALL SHOWPLACE(BURP)      !Let the world know.
            END IF                  !So much for worries.
            IF (ADIGIT) THEN      !Something worked: advance the scan.
              L1 = L2            !Here is where I stopped looking.
              IF (L1.LE.LA) THEN      !Off the end?
                L2 = L1 + 1            !No. Co-ordinate fingers in case of a non-blank.
                IF (ACARD(L1:L1).EQ." ") CALL PASSSPACE      !Only if it is a blank.
              END IF            !Righto, the next non-blank is fingered.
            END IF                  !And L2 is one beyond it if L1 is not off the end.
            EATREAL = ADIGIT      !Report how we feel.
            CALL $SUBOUT("EatReal")      !I am done.
           RETURN                  !So farewell.
          END FUNCTION EATREAL      !Note that the number read is the parameter, NOT the result.

       This prog. is part of a larger collection of routines for the speedy scanning of vast input files. A record of input is read into character variable ACARD, whose last non-blank position is fingered by LA. The scan proceeds from L1, initially set to finger the first non-blank character in ACARD. Each invocation of EATREAL further advances L1 (should a number be read), leaving L1 fingering the next non-blank after the number. This would usually be a comma, and the loop invoking EATREAL invokes a PASSBY(",") to see if it should try for another number.

    Author Comment

    The .CSV file displays a 2 decilmal number 2.5 instead of 2.50. I need to convert that into 000250 or if the number is 1623.88 into 00162388.
    LVL 32

    Accepted Solution

    The .CSV file displays a 2 decilmal number 2.5 instead of 2.50. I need to convert that into 000250 or if the number is 1623.88 into 00162388.

    Are you saying that, given an input file with a line like:


    You want to write it out as:

    (Note: I have 2 more zeroes with my 2.5 example than what you said above.)
    LVL 2

    Assisted Solution

      It is still not clear whether your programme is to read, or to write the data.
       If the numbers are inside your programme, then you can multiply them by 100, round to an integer and write them out.
    eg     V = 1623.88
            WRITE (6,*) INT(V*100)   !Function INT should round to the nearest integer.

       Alternatively,the furrytran FORMAT statement allows the use of the rather odd P specifier which for F-format will shift the decimal place (changing the value presented), as in
           WRITE (6,66) V
       66 FORMAT(2PF9.0)
       would give 162388. but that is still with a decimal point present, and there are no leading zeros.
       You could wtite the output to a character variable, and then fiddle the text to taste (removing the decimal point and adding the leading zeroes), or, if your furrytran supports it, you could use an extension of the I-format. I6 produces a six-digit field, with leading spaces, but I6.6 generates leading zeroes to supply at least six (the .6) digits. Thus,
           WRITE (6,66) INT(V*100)
       66 FORMAT(I6.6)
       Using integers means that you have to be sure that no number will go beyond the range of the integer.

    Featured Post

    Enabling OSINT in Activity Based Intelligence

    Activity based intelligence (ABI) requires access to all available sources of data. Recorded Future allows analysts to observe structured data on the open, deep, and dark web.

    Join & Write a Comment

    Suggested Solutions

    A short article about a problem I had getting the GPS LocationListener working.
    A short article about problems I had with the new location API and permissions in Marshmallow
    The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.
    In this fifth video of the Xpdf series, we discuss and demonstrate the PDFdetach utility, which is able to list and, more importantly, extract attachments that are embedded in PDF files. It does this via a command line interface, making it suitable …

    732 members asked questions and received personalized solutions in the past 7 days.

    Join the community of 500,000 technology professionals and ask your questions.

    Join & Ask a Question

    Need Help in Real-Time?

    Connect with top rated Experts

    19 Experts available now in Live!

    Get 1:1 Help Now