如何计算一系列方程?

时间:2017-12-12 12:34:21

标签: tcl

我遇到一个问题,如果我从文件中得到几个方程式,例如:

na = 1.350
Lambda = 0.2
Seg = 2*na*Lambda
mag = 4
result = mag+Seg*3

如何获得结果的真实价值?谢谢!

2 个答案:

答案 0 :(得分:3)

嗯,你需要的是一点点解析和一点点映射,当然还有eval的创造性使用。

# Assume that the contents of the file is in a big string, $equations

array set vars {}
set map {}
foreach line [split $equations "\n"] {
    if {![regexp {^ *(\w+) *= *(.*)$} $line -> var exp]} {
        error "illegal line '$line'"
    }
    set vars($var) [expr [string map $map $exp]]
    puts "computed $var as $vars($var)"
    lappend map $var \$vars($var)
}
puts "result = $vars(result)"

现在关键点是:

  • regexp {^ *(\w+) *= *(.*)$} $line -> var exp

    解析一行以提取变量,并解析要计算的表达式以获取变量的值。

  • expr [string map $map $exp]

    应用当前映射将$exp转换为Tcl表达式,并将结果计算为表达式。 (正式不安全,但真的方便!)

  • lappend map $var \$vars($var)

    更新映射转换以了解如何读取适当的变量。基本上,Lambda在将来的表达式中将变为$vars(Lambda)

答案 1 :(得分:1)

Donal Fellows的解决方案非常出色(可能需要注意的是,作为另一个标识符的子字符串的标识符可能会有问题),但还有更多方法可以做到这一点:

set equations {
    na = 1.350
    Lambda = 0.2
    Seg = 2*na*Lambda
    mag = 4
    result = mag+Seg*3
}

将这组方程转换为带有标识符键的字典:

% set expressions [dict create {*}[string map {= { }} $equations]]
na 1.350 Lambda 0.2 Seg 2*na*Lambda mag 4 result mag+Seg*3

在字典值中,将美元符号添加到所有标识符(假设所有字符串仅包含字母字符)

dict for {ident expr} $expressions {
    dict set expressions $ident [regsub -all {([[:alpha:]]+)} $expr {$\1}]
}

连续创建与标识符对应的变量,其值根据表达式计算:

dict for {ident expr} $expressions {
    upvar 0 $ident var
    set var [expr $expr]
}

puts "Result: $result"

为简洁起见,这些步骤当然可以合并:

dict for {ident expr} [dict create {*}[string map {= { }} $equations]] {
    upvar 0 $ident var
    set var [expr [regsub -all {([[:alpha:]]+)} $expr {$\1}]]
}

文档: dictexprputsregsubsetstringupvar{*} (syntax)Syntax of Tcl regular expressions