在Go语言中计算公式。

huangapple go评论123阅读模式
英文:

Evaluate formula in Go

问题

使用Go(golang),我想要使用预定义的值对包含公式的字符串进行求值。以下是使用Python的parser模块实现此功能的方法:

package main

import (
	"fmt"
	"go/ast"
	"go/parser"
	"go/token"
	"strconv"
)

func main() {
	x := 8
	expr, _ := parser.ParseExpr("(x + 2) / 10")
	result := evaluate(expr, x)
	fmt.Println(result)
	// 输出 1
}

func evaluate(expr ast.Expr, x int) float64 {
	switch e := expr.(type) {
	case *ast.BinaryExpr:
		left := evaluate(e.X, x)
		right := evaluate(e.Y, x)
		switch e.Op {
		case token.ADD:
			return left + right
		case token.SUB:
			return left - right
		case token.MUL:
			return left * right
		case token.QUO:
			return left / right
		}
	case *ast.BasicLit:
		if e.Kind == token.INT {
			val, _ := strconv.Atoi(e.Value)
			return float64(val)
		}
	case *ast.Ident:
		if e.Name == "x" {
			return float64(x)
		}
	}
	return 0
}

以上是使用Go语言实现的方法,可以对包含公式的字符串进行求值。

英文:

Using Go (golang) I'd like to take a string with a formula and evaluate it with pre-defined values. Here's a way to do it with python's parser module:

x = 8
code = parser.expr("(x + 2) / 10").compile()
print eval(code)
# prints 1

Any idea how to do it with Go?

答案1

得分: 18

这个包可能适合你的需求:https://github.com/Knetic/govaluate

expression, err := govaluate.NewEvaluableExpression("(x + 2) / 10");

parameters := make(map[string]interface{}, 8)
parameters["x"] = 8;

result, err := expression.Evaluate(parameters);
英文:

This package will probably work for your needs: https://github.com/Knetic/govaluate

expression, err := govaluate.NewEvaluableExpression("(x + 2) / 10");

parameters := make(map[string]interface{}, 8)
parameters["x"] = 8;

result, err := expression.Evaluate(parameters);

答案2

得分: 15

你可能需要使用一个解释数学语句的库,或者编写自己的解析器。Python作为一种动态语言,可以在运行时解析和执行Python代码。标准的Go语言不能做到这一点。

如果你想自己编写解析器,Go语言的包会有所帮助。以下是一个示例(在playground上):

import (
	"go/ast"
	"go/parser"
	"go/token"
)

func main() {
	fs := token.NewFileSet()
	tr, _ := parser.ParseExpr("(3-1) * 5")
	ast.Print(fs, tr)
}

生成的AST(抽象语法树)可以遍历和解释,你可以根据需要处理'+'符号(例如将其作为加法运算符处理已存储的值)。

英文:

You will probably need to resort to a library that interprets math statements or have to write your own parser. Python being a dynamic language can parse and execute python code at runtime. Standard Go cannot do that.

If you want to write a parser on your own, the go package will be of help. Example (On play):

import (
	"go/ast"
	"go/parser"
	"go/token"
)

func main() {
	fs := token.NewFileSet()
	tr, _ := parser.ParseExpr("(3-1) * 5")
	ast.Print(fs, tr)
}

The resulting AST (Abstract Syntax Tree) can then be traversed and interpreted as you choose (handling '+' tokens as addition for the now stored values, for example).

答案3

得分: 4

我已经制作了自己的方程求值器,使用了Djikstra的Shunting Yard算法
它支持所有运算符、嵌套括号、函数甚至用户定义的变量。

它是用纯go编写的。

https://github.com/marcmak/calc

英文:

I have made my own equation evaluator, using Djikstra's Shunting Yard Algorithm.
It supports all operators, nested parenthesis, functions and even user defined variables.

It is written in pure go

https://github.com/marcmak/calc

答案4

得分: 2

使用这个代码,你可以动态评估任何公式,并返回true或false:

package main

import (
	"go/token"
	"go/types"
)

func main() {
	fs := token.NewFileSet()
	tv, err := types.Eval(fs, nil, token.NoPos, "(1 + 4) >= 5")
	if err != nil {
		panic(err)
	}
	println(tv.Value.String())
}
英文:

With this code you can evaluate dynamically any formula and return true or false:

package main

import (
	"go/token"
	"go/types"
)

func main() {
	fs := token.NewFileSet()
	tv, err := types.Eval(fs, nil, token.NoPos, "(1 + 4) >= 5")
	if err != nil {
		panic(err)
	}
	println(tv.Value.String())
}

答案5

得分: 2

go-exprtk 包可以满足您动态评估任何类型的数学表达式的各种需求。

package main

import (
	"fmt"

	"github.com/Pramod-Devireddy/go-exprtk"
)

func main() {
	exprtkObj := exprtk.NewExprtk()

	exprtkObj.SetExpression("(x + 2) / 10")

	exprtkObj.AddDoubleVariable("x")

	exprtkObj.CompileExpression()
	
	exprtkObj.SetDoubleVariableValue("x", 8)

	fmt.Println(exprtkObj.GetEvaluatedValue())
}

这个包具有许多功能

英文:

go-exprtk package will probably meet all kinds of your needs to evaluate any kind of mathematical expression dynamically.

package main

import (
	"fmt"

	"github.com/Pramod-Devireddy/go-exprtk"
)

func main() {
	exprtkObj := exprtk.NewExprtk()

	exprtkObj.SetExpression("(x + 2) / 10")

	exprtkObj.AddDoubleVariable("x")

	exprtkObj.CompileExpression()
	
	exprtkObj.SetDoubleVariableValue("x", 8)

	fmt.Println(exprtkObj.GetEvaluatedValue())
}

This package has many capabilities

答案6

得分: 1

在Go语言中没有这样的模块。你需要自己构建。你可以使用go包的子包,但它们可能对你的应用程序来说过于复杂。

英文:

There is no such module in Go. You have to build your own. You could use subpackages of the go package, but they might be overkill for your application.

答案7

得分: 1

对于表达式或程序的求值,您可以使用lex和yacc构建词法分析器和语法分析器,并精确指定您的迷你语言的语法和语义。计算器一直是一个标准的yacc示例,而go版本的lex和yacc也不例外。

这是一个指向calc示例的链接:https://github.com/golang-samples/yacc/tree/master/simple

英文:

For expression or program evaluation, you can build a lexer and parser using lex and yacc, and specify exactly the syntax and semantics of your mini-language. A calculator has always been a standard yacc example, and the go versions of lex and yacc are no different.

Here's a pointer to the calc example: https://github.com/golang-samples/yacc/tree/master/simple

答案8

得分: 0

没有内置的功能可以做到这一点(请记住,Go语言不是一种动态语言)。

不过,你可以始终使用bufio.Scanner并构建自己的解析器。

英文:

There's nothing built in that could do that (remember, Go is not a dynamic language).

However, you can always use bufio.Scanner and build your own parser.

答案9

得分: 0

我找到了这个链接:https://github.com/sbinet/go-eval

它似乎是一个用于Go的评估循环。

go get github.com/sbinet/go-eval/cmd/go-eval
go install github.com/sbinet/go-eval/cmd/go-eval
go-eval
英文:

Googling around I found this: https://github.com/sbinet/go-eval

It appears to be an eval loop for Go.

go get github.com/sbinet/go-eval/cmd/go-eval
go install github.com/sbinet/go-eval/cmd/go-eval
go-eval

huangapple
  • 本文由 发表于 2014年5月29日 07:18:26
  • 转载请务必保留本文链接:https://go.coder-hub.com/23923383.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定