math-engine icon indicating copy to clipboard operation
math-engine copied to clipboard

浮点数相乘

Open GoldThree opened this issue 3 years ago • 3 comments

0.7*360=251.99999999999997

GoldThree avatar Nov 22 '21 09:11 GoldThree

这种好像没有做处理 :monocle_face:

GoldThree avatar Nov 22 '21 09:11 GoldThree

可以使用 https://github.com/shopspring/decimal 做处理

package main

import (
	"fmt"

	"github.com/dengsgo/math-engine/engine"
	"github.com/shopspring/decimal"
)

func main() {
	s := "0.7*360"
	// call top level function
	r, err := engine.ParseAndExec(s)
	if err != nil {
		fmt.Println(err)
	}
	p, err := decimal.NewFromString(fmt.Sprintf("%f", r))
	if err != nil {
		panic(err)
	}

	fmt.Println(p) //252
}

本来想用 decimal 处理浮点数精度的问题,但是发现会损失精度

// Top level function
// Analytical expression and execution
// err is not nil if an error occurs (including arithmetic runtime errors)
func ParseAndExec(s string) (r float64, err error) {
	toks, err := Parse(s)
	if err != nil {
		return 0, err
	}
	ast := NewAST(toks, s)
	if ast.Err != nil {
		return 0, ast.Err
	}
	ar := ast.ParseExpression()
	if ast.Err != nil {
		return 0, ast.Err
	}
	defer func() {
		if e := recover(); e != nil {
			err = e.(error)
		}
	}()
	res, err := decimal.NewFromString(fmt.Sprintf("%f", ExprASTResult(ar)))
	if err != nil {
		return 0, err
	}
	r, _ = res.Float64()
	return r, err
}

=== RUN TestParseAndExecSimple util_test.go:85: {3^4.5 140.29611541307906} ParseAndExec: 140.296115 util_test.go:85: {3.5^4.5 280.7412308013823} ParseAndExec: 280.741231 util_test.go:85: {pi 3.141592653589793} ParseAndExec: 3.141593 --- FAIL: TestParseAndExecSimple (0.00s)

FAIL

jimyag avatar Sep 07 '22 09:09 jimyag

应该是要你保留多少个小数吧?这个看起来是被四舍五入了

jacktrane avatar Nov 03 '22 08:11 jacktrane