字符串到 Python 3.10 中的浮点数。字符串的哪种格式?

String to Float in Python 3.10. Which format of the string?

提问人:RaHeSch 提问时间:12/11/2022 最后编辑:RaHeSch 更新时间:12/11/2022 访问量:191

问:

我想使用 Python 3.10 将字符串转换为浮点数。

问题出在字符串的格式上。例如:

"  3.841-11"

它代表 3.841E-011。

我尝试了经典的

float("  3.841-11")

但这给出了一个错误。

仅仅更改这个字符串是没有解决方案的,因为我想读取一个更大的文件,如下所示:

$$
$$  GRID Data
$$

GRID           1        -44.0332667.9   -2.55271
GRID           2        -39.1406667.9   -2.26907
GRID           3        -34.2481667.9   -1.98544
GRID           4        -29.3555667.9   -1.70181
GRID           5        -24.4629667.9   -1.41817
GRID           6        -19.5703667.9   -1.13454
GRID           7        -14.6777667.9   -.850903
GRID           8        -9.78516667.9   -.567269
GRID           9        -4.89258667.9   -.283634
GRID          10        3.055-13667.9   3.841-11
GRID          11        4.892579667.9   .2836343

这是我的代码:

    def read_fem(location):  
        mesh = open(location, 'r').read().splitlines()
    
        point = []
    
        for i in range(1, len(mesh)):
            if '$' not in mesh[i]:
    
                if 'GRID' in mesh[i]:
                    number = int(mesh[i][8:16])
                    x = float(mesh[i][24:32])
                    y = float(mesh[i][32:40])
                    z = float(mesh[i][40:48])
    
                    point.append([number, x, y, z])

感谢每一个答案。

python-3.x 浮点 熊猫

评论

1赞 mozway 12/11/2022
第三列所有数字的尾随呢?667.9

答:

2赞 mozway 12/11/2022 #1

使用

IMO,最好不要手动解析您的文件,而是使用库。 是理想的选择。首先用 pandas.read_fwf 读取文件,然后在转换为浮点数之前以正确的指数形式在前面加上一个数字:replace-+

import pandas as pd

data = pd.read_fwf('data.txt', sep='\s+', colspecs=[(8,16),(24,32),(32,40),(40,48)])

# fix the incorrect numbers
# and convert to float
data.update(data.select_dtypes(exclude='number')
                .apply(lambda s: s.str.replace(r'(?<=\d)(?=[-+])', 'e', regex=True)
                                  .astype(float))
            )

# convert to list
out = data.to_numpy().tolist()

输出:

[[1, -44.0332, 667.9, -2.55271],
 [2, -39.1406, 667.9, -2.26907],
 [3, -34.2481, 667.9, -1.98544],
 [4, -29.3555, 667.9, -1.70181],
 [5, -24.4629, 667.9, -1.41817],
 [6, -19.5703, 667.9, -1.13454],
 [7, -14.6777, 667.9, -0.850903],
 [8, -9.78516, 667.9, -0.567269],
 [9, -4.89258, 667.9, -0.283634],
 [10, 3.055e-13, 667.9, 3.841e-11],
 [11, 4.892579, 667.9, 0.2836343]]

较旧的答案

在转换为之前替换为:-e-float

s = '3.841-11'

out = float(s.replace('-', 'e-'))

输出:3.841e-11

如果可以的话,一种更通用的方法是使用正则表达式:e+

import re

s = '3.841+4'

out = float(re.sub(r'(?=[-+])', 'e', s))

输出:38410.0

用于修复文件的短程序

这将读取并输出 中的固定浮点数。data.txtdata_clean.txt

import re
with open('data.txt') as f, open('data_clean.txt', 'w') as f_out:
    f_out.write(re.sub(r'(?<=\d)(?=[-+])', 'e', f.read()))

我还看到你有像这样的数字,这将是无效的,因为指数必须是一个整数。您还可以修复以下问题:3.055-13667.9

import re
with open('data.txt') as f, open('data_clean.txt', 'w') as f_out:
    f_out.write(re.sub(r'(?<=\d)([-+])(\d+.\d?)', lambda m: f'e{m.group(1)}{int(float(m.group(2)))}', f.read()))

固定文件:

$$
$$  GRID Data
$$

GRID           1        -44.0332667.9   -2.55271
GRID           2        -39.1406667.9   -2.26907
GRID           3        -34.2481667.9   -1.98544
GRID           4        -29.3555667.9   -1.70181
GRID           5        -24.4629667.9   -1.41817
GRID           6        -19.5703667.9   -1.13454
GRID           7        -14.6777667.9   -.850903
GRID           8        -9.78516667.9   -.567269
GRID           9        -4.89258667.9   -.283634
GRID          10        3.055e-13667   3.841e-11
GRID          11        4.892579667.9   .2836343

评论

0赞 RaHeSch 12/11/2022
感谢您的回答!我修改了我的问题。我想读一个更大的文件,所以我想我不能像这样解决它。
0赞 Mark Ransom 12/11/2022
@RaHeSch文件大小无关紧要,您可以将其逐个应用于文件中的每个值或行。
0赞 Mark Ransom 12/11/2022
如果正则表达式强制在 +/- 之前添加一个数字,则该正则表达式可能会更可靠。
0赞 RaHeSch 12/11/2022
@MarkRansom我试过了,但是这一行现在将 e 放在每个“-”之前。例如,'-2.55271' -> ' e-2.55271'
0赞 mozway 12/11/2022
@RaHeSch您应该考虑使用 csv/pandas 来读取文件,那么您可以应用转换以转换为浮点数
0赞 ScottC 12/11/2022 #2

以下程序将:

  • 假设文件被命名为:grid_data.txt
  • 寻找用数字包围的连字符,例如。 并转换为3.841-113.841e-11
  • 忽略数字开头的连字符,例如。-44.0332

该函数允许转换发生。fix_float()

  • 使用的正则表达式是\d(-)\d

法典:

import re

pattern = re.compile(r'\d(-)\d')

def fix_float(m):
    val = m.group(0).replace('-','e-')
    return val

def read_fem(location):  
    mesh = open(location, 'r').read().splitlines()
    point = []

    for m in mesh:
        if '$' not in m:
            if 'GRID' in m:
                number = int(m[8:16])
                x = float(pattern.sub(fix_float, m[24:32]))
                y = float(pattern.sub(fix_float, m[32:40]))
                z = float(pattern.sub(fix_float, m[40:48]))

                point.append([number, x, y, z])
    return point


# Extract the data from the file                
data = read_fem('grid_data.txt')

# Display the data
for point in data:
    print(point)

输出:

[1, -44.0332, 667.9, -2.55271]
[2, -39.1406, 667.9, -2.26907]
[3, -34.2481, 667.9, -1.98544]
[4, -29.3555, 667.9, -1.70181]
[5, -24.4629, 667.9, -1.41817]
[6, -19.5703, 667.9, -1.13454]
[7, -14.6777, 667.9, -0.850903]
[8, -9.78516, 667.9, -0.567269]
[9, -4.89258, 667.9, -0.283634]
[10, 3.055e-13, 667.9, 3.841e-11]
[11, 4.892579, 667.9, 0.2836343]