Path: utzoo!utgpu!jarvis.csri.toronto.edu!mailrus!ames!sun-barr!newstop!sun!dgh!dgh From: dgh%dgh@Sun.COM (David Hough) Newsgroups: comp.lang.fortran Subject: What's a legitimate floating-point number? (somewhat long) Keywords: .e0 Message-ID: <128706@sun.Eng.Sun.COM> Date: 2 Dec 89 03:17:56 GMT Sender: news@sun.Eng.Sun.COM Lines: 140 It's an interesting exercise trying to implement standard Fortran I/O, given the complexity of list-directed, formatted with BLANK=ZERO, formatted with BLANK=NULL. Add namelist I/O if you want to be commercially successful. Add VAX VMS compatibility too if you want to steal DEC's market share. The latter is tricky. It turns out that under F3.0, for instance, VAX VMS Fortran will accept ".e0" and "++1" as legitimate floating-point numbers, both returning the value 0, which is just what you expected, of course, if you understood that part of the Fortran-77 standard which says 13.5.9.2.1 The input field consists of an optional sign, followed by a string of digits optionally containing a decimal point. Well if the "string of digits" can be an EMPTY string of digits, then you'll understand that .e0 is equivalent to 0.e0 and ++1 is equivalent to 0+1 which is equivalent to 0e+1. Many people would consider that stretching the intent of the standard, but it turns out that there are a lot of data files containing just a point that programs expect to convert to a number, zero presumably. And we've had bug reports because we didn't accept ".e0" in list-directed input. Bob Corbett thought of the "++1" example; we haven't yet had a request for VAX VMX compatibility in that respect. I decided to investigate what it was we did accept. It turns out that at least Sun Fortran 1.1 and 1.2 produce the following results from the test program reproduced at the end of this note: error? input string format no error input > . e0x < ZERO fmt (BZ,e5.1) x 0. no error input > . e0x < NULL fmt (BN,e5.1) x 0. ERROR input > . e0x < * fmt x -1.00000 no error input > .e0x < ZERO fmt (BZ,e5.1) x 0. no error input > .e0x < NULL fmt (BN,e5.1) x 0. ERROR input > .e0x < * fmt x -1.00000 no error input >. e0x < ZERO fmt (BZ,e5.1) x 0. no error input >. e0x < NULL fmt (BN,e5.1) x 0. ERROR input >. e0x < * fmt x -1.00000 ERROR input >.e0x < ZERO fmt (BZ,e5.1) x -1.00000 ERROR input >.e0x < NULL fmt (BN,e5.1) x -1.00000 ERROR input >.e0x < * fmt x -1.00000 no error input >.e0 < ZERO fmt (BZ,e5.1) x 0. no error input >.e0 < NULL fmt (BN,e5.1) x 0. ERROR input >.e0 < * fmt x -1.00000 ERROR input >++1x < ZERO fmt (BZ,e5.1) x -1.00000 ERROR input >++1x < NULL fmt (BN,e5.1) x -1.00000 ERROR input >++1x < * fmt x -1.00000 ERROR input >++1 < ZERO fmt (BZ,e5.1) x -1.00000 ERROR input >++1 < NULL fmt (BN,e5.1) x -1.00000 ERROR input >++1 < * fmt x -1.00000 The difference between .e0 and .e0x is a little hard to fathom, but otherwise the rule seems to be that .e0 is OK for formatted input, even when blanks are supposed to be ignored, but is not OK for list-directed input. This doesn't make a lot of sense. As an experiment I changed the floating-point number scanner so that it produced the following output: no error input > . e0x < ZERO fmt (BZ,e5.1) x 0. ERROR input > . e0x < NULL fmt (BN,e5.1) x -1.00000 ERROR input > . e0x < * fmt x -1.00000 ERROR input > .e0x < ZERO fmt (BZ,e5.1) x -1.00000 ERROR input > .e0x < NULL fmt (BN,e5.1) x -1.00000 ERROR input > .e0x < * fmt x -1.00000 no error input >. e0x < ZERO fmt (BZ,e5.1) x 0. ERROR input >. e0x < NULL fmt (BN,e5.1) x -1.00000 ERROR input >. e0x < * fmt x -1.00000 ERROR input >.e0x < ZERO fmt (BZ,e5.1) x -1.00000 ERROR input >.e0x < NULL fmt (BN,e5.1) x -1.00000 ERROR input >.e0x < * fmt x -1.00000 ERROR input >.e0 < ZERO fmt (BZ,e5.1) x -1.00000 ERROR input >.e0 < NULL fmt (BN,e5.1) x -1.00000 ERROR input >.e0 < * fmt x -1.00000 ERROR input >++1x < ZERO fmt (BZ,e5.1) x -1.00000 ERROR input >++1x < NULL fmt (BN,e5.1) x -1.00000 ERROR input >++1x < * fmt x -1.00000 ERROR input >++1 < ZERO fmt (BZ,e5.1) x -1.00000 ERROR input >++1 < NULL fmt (BN,e5.1) x -1.00000 ERROR input >++1 < * fmt x -1.00000 Working this way, .e0 is never accepted and ". e0" is accepted only when blanks are to be interpreted as zeros. (leading blanks are perhaps not supposed to count). Is this an improvement? For those who are curious, the test program is subroutine test(d) real x character*10 s,d s = "(BZ,e5.1)" x=-1 read (d,s, ERR = 3) x print *," no error "," input >",d,"< ZERO fmt ",s," x ",x goto 31 3 continue print *," ERROR "," input >",d,"< ZERO fmt ",s," x ",x 31 continue s = "(BN,e5.1)" x=-1 read (d,s, ERR = 2) x print *," no error "," input >",d,"< NULL fmt ",s," x ",x goto 21 2 continue print *," ERROR "," input >",d,"< NULL fmt ",s," x ",x 21 continue s = " " x=-1 read (d,*, ERR = 1) x print *," no error "," input >",d,"< * fmt ",s," x ",x goto 11 1 continue print *," ERROR "," input >",d,"< * fmt ",s," x ",x 11 continue end character*10 d d = " . e0x" call test(d) d = " .e0x" call test(d) d = ". e0x" call test(d) d = ".e0x" call test(d) d = ".e0" call test(d) d = "++1x" call test(d) d = "++1" call test(d) end David Hough na.hough@na-net.stanford.edu