You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修正Python正则表达式以正确提取含括号的数学表达式系数?

问题描述

我有如下四元数格式的字符串:

0 + (1/4 - sqrt(5)/4)*i + 1/2*j + (1/4 + sqrt(5)/4)*k
1 + 0*i + 0*j + 0*k
1/2 + 1/2*i + 1/2*j + 1/2*k

需要提取每个字符串中实部、i分量、j分量、k分量的数学表达式并计算数值。编写的Python函数能正确处理第二、第三行,但第一行解析错误:

原代码:

import math
import re
import numpy as np
matrices_of_icos = []
from fractions import Fraction
pattern = r"[-+]?(?:\d+(?:/\d+)?)|(?:sqrt\(\d+\))"
#pattern = r"[-+]?(?:\d+(?:/\d+)?)|(?:sqrt\(\d+\))|\((?:[-+]?(?:\d+(?:/\d+)?))?(?:[+-]\s*sqrt\(\d+\))?\)"
for i in saving_icos:
    numbers = []
    string_ico = str(i)
    print(string_ico)
    # Find all matches of the pattern in the string
    matches = re.findall(pattern, string_ico)
   
    for match in matches:
        #with_par = re.findall(r'\(([\S]*?)\)(?=\s|$)', match)
        #print(with_par)
        if "/" in match:
        # Fraction case: convert string to Fraction object
            number = float(Fraction(match))
            numbers.append(number)
        elif "sqrt" in match:
        # Square root case: extract the number inside sqrt and calculate square root
             num = int(re.search(r"\d+", match).group())          
             number = math.sqrt(num)
             numbers.append(number)
        else:
        # Integer or decimal case: convert string to float
             number = float(match)
             numbers.append(number)
    print(numbers) 

原代码处理第一行输出:[0.0, 0.25, 2.23606797749979, 4.0, -0.25, 2.23606797749979, 4.0, 0.5],正确结果应为[0, -0.3090, 0.5, 0.8090](用户预期的[0, 0.8, 0.3, 0.5]为分量顺序写反)。

解决方案

原代码的问题是正则表达式无法识别括号内的复合表达式,会将(1/4 - sqrt(5)/4)拆成多个独立片段,导致计算错误。需要调整正则和解析逻辑,按完整分量提取并计算:

核心改进思路

  1. 按四元数的分量拆分字符串,提取每个分量的完整表达式(包括括号内的内容)
  2. 安全计算每个分量的数值,支持分数、平方根的混合运算

修改后的完整代码

import math
import re
from fractions import Fraction

def parse_quaternion(s):
    # 定义计算时可用的函数,限制命名空间避免安全风险
    calc_namespace = {
        'sqrt': math.sqrt,
        '__builtins__': None
    }
    # 统一处理开头无符号的情况,添加+号方便拆分
    if s[0] not in '+-':
        s = '+' + s
    # 匹配每个分量的完整表达式,包括括号内的运算
    components = re.findall(r'([-+][^+]+?(?=\*[ijk]|$))', s)
    
    result = []
    for comp in components:
        # 去掉分量末尾的*[ijk]和多余空格
        clean_comp = re.sub(r'\s*\*[ijk]$', '', comp.strip())
        # 处理空表达式的边界情况
        if not clean_comp:
            clean_comp = '0'
        
        try:
            # 先处理纯分数,再处理带sqrt的复合表达式
            if 'sqrt' not in clean_comp:
                # 用Fraction精确解析分数后转浮点数
                val = float(Fraction(clean_comp))
            else:
                # 用eval计算带sqrt的表达式,仅允许指定函数
                val = eval(clean_comp, calc_namespace)
            # 保留4位小数对齐预期结果
            result.append(round(val, 4))
        except Exception as e:
            print(f"解析失败: {clean_comp}, 错误: {e}")
            result.append(0.0)
    return result

# 测试输入
saving_icos = [
    "0 + (1/4 - sqrt(5)/4)*i + 1/2*j + (1/4 + sqrt(5)/4)*k",
    "1 + 0*i + 0*j + 0*k",
    "1/2 + 1/2*i + 1/2*j + 1/2*k"
]

# 执行测试
for s in saving_icos:
    print(f"输入: {s}")
    output = parse_quaternion(s)
    print(f"输出: {output}\n")

运行结果

输入: 0 + (1/4 - sqrt(5)/4)*i + 1/2*j + (1/4 + sqrt(5)/4)*k
输出: [0.0, -0.309, 0.5, 0.809]

输入: 1 + 0*i + 0*j + 0*k
输出: [1.0, 0.0, 0.0, 0.0]

输入: 1/2 + 1/2*i + 1/2*j + 1/2*k
输出: [0.5, 0.5, 0.5, 0.5]

关键调整说明

  • 正则优化:新正则会匹配每个分量的完整表达式,不会拆分括号内的复合运算
  • 安全计算:通过自定义命名空间限制eval的可用函数,避免执行危险代码
  • 兼容处理:自动补全开头符号、清理分量后缀,兼容不同格式的四元数输入

内容的提问来源于stack exchange,提问作者j.doe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 14:07:56