7

I am trying to read a Fortran double-precision number like 1.2345D+02 into python, but I got the following error:

>>> float('1.2345D+02')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid literal for float(): 1.2345D+02

By following the advice on Python scientific notation using D instead of E, I tried numpy but I also get the same error:

import numpy
>>> numpy.float("1.2345D+02")
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: invalid literal for float(): 1.2345D+02

Is there a solution in Python to read those double precision numbers without just changing the 'D' to 'E'?

EDIT: I replaced a bad syntax on the strings. But still I get errors.

Community
  • 1
  • 1
iluvatar
  • 872
  • 10
  • 21
  • Just a heads up that maybe the `fortranformat` Python library (on PyPI) can help - I should probably disclose that I'm the author. – Brendan Jun 29 '11 at 18:32

2 Answers2

5

What's wrong with float(str.replace("D", "E"))?

Please note, numpy DOES support fortran notation: numpy.float("1.2345D+02").

You seem to have some deeper purpose, perhaps shedding light on it would help.

orlp
  • 112,504
  • 36
  • 218
  • 315
  • In general, nothing is wrong with replacing "D" with "E". I just want to know if there is a "native" solution. If numpy supports fortran notation, why is it failing as shown in the example? Yes, I need to parse some huge fortran-generated data files and to extract some particular data. Thanks! – iluvatar May 13 '11 at 08:50
  • 1
    Because `numpy.float(1.2345D+02)` would be parsed by the python interpreter as a call to `numpy.float` with `1.2345D+02`. `1.2345D+02` is unknown to the python interpreter so it gives an error. `"1.2345D+02"` is a string, which is perfectly fine. – orlp May 13 '11 at 08:58
  • Thanks. Actually it was a typo on my example. I already corrected it but the error (another one) remains. – iluvatar May 13 '11 at 09:01
  • Possibly you are using different versions of numpy – John La Rooy May 13 '11 at 09:32
  • 8
    At least `numpy 1.5.1` *doesn't* support `numpy.float("1.2345D+02")`. – jfs May 13 '11 at 10:37
  • Use f2py to create .pyd file. Run it from Python. When Fortran send a double precision number to Python, Python will accept it without the `D`. But, if you already have the fortran-generated data files, perhaps you can use the solution by @nightcracker. – riza May 13 '11 at 12:49
  • Thanks, @J.F. Sebastian , I have numpy 1.5.1 and that is the reason. – iluvatar May 13 '11 at 12:58
  • you also need to be careful that some Fortran compilers will print numbers larger than 1.e99 dropping the "E", so you'll get 0.1+100 which is 10**99 python doesn't like this format either. – Michael Zingale Feb 16 '16 at 15:38
  • The first option is great; thanks. This could be made generic by using `float(re.sub('[dD]', 'e', str))` instead. Somehow, it seems that recent versions of numpy has stopped support for the fortran notation. (I am using numpy v1.17.4.) – Ombrophile Sep 30 '21 at 07:28
1

The substitution can be made a bit more careful by using a regular expression:

import re
re_dbl_fort = re.compile(r'(\d*\.\d+)[dD]([-+]?\d+)')

text = 'DEW=[0.242D+03 -4.320D-06]'
re_dbl_fort.sub(r'\1E\2', text)
# DEW=[0.242E+03 -4.320E-06]

Or if you have a list of strings (lines) read from a file using readlines():

lines = ['REPORT CARD\n', 'GRADE: D+ (1.3D+00/4.0D+00)\n']
for ln, line in enumerate(lines):
    res = re_dbl_fort.sub(r'\1E\2', line)
    if line != res:
        lines[ln] = res
# ['REPORT CARD\n', 'GRADE: D+ (1.3E+00/4.0E+00)\n']
Mike T
  • 41,085
  • 18
  • 152
  • 203