определение числителя и знаменателя в относительно сложном математическом выражении с использованием Python - PullRequest
6 голосов
/ 09 февраля 2011

Я пытаюсь преобразовать ввод калькулятора в LaTeX. если пользователь вводит это:

(3x^(x+(5/x)+(x/33))+y)/(32 + 5)

Я должен преобразовать это в это:

frac{3x^(x+frac{5}{x}+frac{x}{33})+y}{32 + 5x}

однако у меня возникают проблемы с определением, когда числитель начинается и заканчивается. Есть предложения?

Ответы [ 3 ]

5 голосов
/ 09 февраля 2011

Посмотрите на компилятор

compiler.parse('(3*x**(x+(5/x)+(x/33))+y)/(32 + 5)')

возвращает

Module(None, Stmt([Discard(Div((Add((Mul((Const(3), Power((Name('x'), Add((Add((Name('x'), Div((Const(5), Name('x'))))), Div((Name('x'), Const(33))))))))), Name('y'))), Add((Const(32), Const(5))))))]))

, который легче конвертировать в код LaTeX. Вам нужно будет написать методы, которые обрабатывают каждый код (Div, Add, Const, Name, Power, ...) и его параметры рекурсивно и возвращают соответствующий код LateX.

4 голосов
/ 09 февраля 2011

Пакет для этого вида преобразования уже существует: Py2Tex

Если вы хотите использовать этот пакет повторно, вы можете использовать класс py2tex.Interpret.

2 голосов
/ 09 февраля 2011

Если вы хотите использовать точный синтаксис из своего вопроса, вы можете написать парсер для калькулятора :

#!/usr/bin/env python
from operator import add, div, mul, sub

from lepl  import Any, Delayed, Digit, Drop, DroppedSpace, Eos
from sympy import Symbol, latex, pprint

def Power(tokens):
    """x**(y**z)"""
    return reduce(lambda p, b: pow(b, p), reversed(tokens))

def Arithm(tokens):
    """(x op1 y) op2 z ..."""
    OP = { '*': mul, '/': div, '+': add, '-': sub, }
    tokens = iter(tokens)
    a = next(tokens)
    for op, b in zip(tokens, tokens):
        a = OP[op](a, b)
    return a

def makeparser():
    expr = Delayed()
    number = Digit()[1:,...] >> int # \d+
    symbol = Any('xyz') >> (lambda x: Symbol(bytes(x))) # unicode -> str
    muldiv_op = Any('*/')[:1] > (lambda x: x[0] if x else '*') # xy -> x*y
    power_op = Drop('^') | Drop('**') # both stand for pow(x, y)

    with DroppedSpace(): # ignore spaces
        term = number | symbol | Drop('(') & expr & Drop(')')
        power   = term & (power_op  & term)[:] > Power
        factor = power & (muldiv_op & power)[:] > Arithm
        expr += factor & (Any('-+') & factor)[:] > Arithm
        line = expr & Eos()
    return line.get_parse()

parse = makeparser()
[expr] = parse('(3x^(x+(5/x)+(x/33))+y)/(32 + 5)')
pprint(expr)
print(latex(expr))

выход

        34⋅x   5
        ──── + ─
         33    x
y    3⋅x        
── + ───────────
37        37    
$\frac{1}{37} y + \frac{3}{37} x^{\frac{34}{33} x + \frac{5}{x}}$

В целом, может быть предпочтительнее использовать синтаксис для существующего языка, такого как Python.

...