소스 검색

#65 fn: BESSELI and BESSELJ

xuri 4 년 전
부모
커밋
6e812a27c6
2개의 변경된 파일73개의 추가작업 그리고 0개의 파일을 삭제
  1. 60 0
      calc.go
  2. 13 0
      calc_test.go

+ 60 - 0
calc.go

@@ -227,6 +227,8 @@ var tokenPriority = map[string]int{
 //    AVERAGE
 //    AVERAGEA
 //    BASE
+//    BESSELI
+//    BESSELJ
 //    BIN2DEC
 //    BIN2HEX
 //    BIN2OCT
@@ -1226,6 +1228,64 @@ func formulaCriteriaEval(val string, criteria *formulaCriteria) (result bool, er
 
 // Engineering Functions
 
+// BESSELI function the modified Bessel function, which is equivalent to the
+// Bessel function evaluated for purely imaginary arguments. The syntax of
+// the Besseli function is:
+//
+//    BESSELI(x,n)
+//
+func (fn *formulaFuncs) BESSELI(argsList *list.List) formulaArg {
+	if argsList.Len() != 2 {
+		return newErrorFormulaArg(formulaErrorVALUE, "BESSELI requires 2 numeric arguments")
+	}
+	return fn.bassel(argsList, true)
+}
+
+// BESSELJ function returns the Bessel function, Jn(x), for a specified order
+// and value of x. The syntax of the function is:
+//
+//    BESSELJ(x,n)
+//
+func (fn *formulaFuncs) BESSELJ(argsList *list.List) formulaArg {
+	if argsList.Len() != 2 {
+		return newErrorFormulaArg(formulaErrorVALUE, "BESSELJ requires 2 numeric arguments")
+	}
+	return fn.bassel(argsList, false)
+}
+
+// bassel is an implementation of the formula function BESSELI and BESSELJ.
+func (fn *formulaFuncs) bassel(argsList *list.List, modfied bool) formulaArg {
+	x, n := argsList.Front().Value.(formulaArg).ToNumber(), argsList.Back().Value.(formulaArg).ToNumber()
+	if x.Type != ArgNumber {
+		return x
+	}
+	if n.Type != ArgNumber {
+		return n
+	}
+	max, x1 := 100, x.Number*0.5
+	x2 := x1 * x1
+	x1 = math.Pow(x1, n.Number)
+	n1, n2, n3, n4, add := fact(n.Number), 1.0, 0.0, n.Number, false
+	result := x1 / n1
+	t := result * 0.9
+	for result != t && max != 0 {
+		x1 *= x2
+		n3++
+		n1 *= n3
+		n4++
+		n2 *= n4
+		t = result
+		if modfied || add {
+			result += (x1 / n1 / n2)
+		} else {
+			result -= (x1 / n1 / n2)
+		}
+		max--
+		add = !add
+	}
+	return newNumberFormulaArg(result)
+}
+
 // BIN2DEC function converts a Binary (a base-2 number) into a decimal number.
 // The syntax of the function is:
 //

+ 13 - 0
calc_test.go

@@ -47,6 +47,11 @@ func TestCalcCellValue(t *testing.T) {
 		"=2>=3": "FALSE",
 		"=1&2":  "12",
 		// Engineering Functions
+		// BESSELI
+		"=BESSELI(4.5,1)": "15.389222753735925",
+		"=BESSELI(32,1)":  "5.502845511211247e+12",
+		// BESSELJ
+		"=BESSELJ(1.9,2)": "0.329925727692387",
 		// BIN2DEC
 		"=BIN2DEC(\"10\")":         "2",
 		"=BIN2DEC(\"11\")":         "3",
@@ -1008,6 +1013,14 @@ func TestCalcCellValue(t *testing.T) {
 	mathCalcError := map[string]string{
 		"=1/0": "#DIV/0!",
 		// Engineering Functions
+		// BESSELI
+		"=BESSELI()":       "BESSELI requires 2 numeric arguments",
+		"=BESSELI(\"\",0)": "strconv.ParseFloat: parsing \"\": invalid syntax",
+		"=BESSELI(0,\"\")": "strconv.ParseFloat: parsing \"\": invalid syntax",
+		// BESSELJ
+		"=BESSELJ()":       "BESSELJ requires 2 numeric arguments",
+		"=BESSELJ(\"\",0)": "strconv.ParseFloat: parsing \"\": invalid syntax",
+		"=BESSELJ(0,\"\")": "strconv.ParseFloat: parsing \"\": invalid syntax",
 		// BIN2DEC
 		"=BIN2DEC()":     "BIN2DEC requires 1 numeric argument",
 		"=BIN2DEC(\"\")": "strconv.ParseFloat: parsing \"\": invalid syntax",