From 4ac32278ff3e8951307274ceb4dd0043d606d5a0 Mon Sep 17 00:00:00 2001 From: xuri Date: Sun, 31 Jan 2021 13:15:10 +0800 Subject: [PATCH] Fix hyperbolic cotangent calculation incorrect and unit test --- calc.go | 179 +++++++++++++++++++++++++++------------------------ calc_test.go | 120 ++++++++++++++++++---------------- 2 files changed, 162 insertions(+), 137 deletions(-) diff --git a/calc.go b/calc.go index ecd5f0cd..eed0f5d1 100644 --- a/calc.go +++ b/calc.go @@ -344,8 +344,7 @@ func newErrorFormulaArg(formulaError, msg string) formulaArg { // func (f *File) evalInfixExp(sheet string, tokens []efp.Token) (efp.Token, error) { var err error - opdStack, optStack, opfStack, opfdStack, opftStack := NewStack(), NewStack(), NewStack(), NewStack(), NewStack() - argsList := list.New() + opdStack, optStack, opfStack, opfdStack, opftStack, argsStack := NewStack(), NewStack(), NewStack(), NewStack(), NewStack(), NewStack() for i := 0; i < len(tokens); i++ { token := tokens[i] @@ -359,6 +358,7 @@ func (f *File) evalInfixExp(sheet string, tokens []efp.Token) (efp.Token, error) // function start if token.TType == efp.TokenTypeFunction && token.TSubType == efp.TokenSubTypeStart { opfStack.Push(token) + argsStack.Push(list.New().Init()) continue } @@ -396,7 +396,7 @@ func (f *File) evalInfixExp(sheet string, tokens []efp.Token) (efp.Token, error) if result.Type == ArgUnknown { return efp.Token{}, errors.New(formulaErrorVALUE) } - argsList.PushBack(result) + argsStack.Peek().(*list.List).PushBack(result) continue } } @@ -417,7 +417,7 @@ func (f *File) evalInfixExp(sheet string, tokens []efp.Token) (efp.Token, error) opftStack.Pop() } if !opfdStack.Empty() { - argsList.PushBack(formulaArg{ + argsStack.Peek().(*list.List).PushBack(formulaArg{ String: opfdStack.Pop().(efp.Token).TValue, Type: ArgString, }) @@ -431,7 +431,7 @@ func (f *File) evalInfixExp(sheet string, tokens []efp.Token) (efp.Token, error) // current token is text if token.TType == efp.TokenTypeOperand && token.TSubType == efp.TokenSubTypeText { - argsList.PushBack(formulaArg{ + argsStack.Peek().(*list.List).PushBack(formulaArg{ String: token.TValue, Type: ArgString, }) @@ -450,26 +450,26 @@ func (f *File) evalInfixExp(sheet string, tokens []efp.Token) (efp.Token, error) // push opfd to args if opfdStack.Len() > 0 { - argsList.PushBack(formulaArg{ + argsStack.Peek().(*list.List).PushBack(formulaArg{ String: opfdStack.Pop().(efp.Token).TValue, Type: ArgString, }) } - // call formula function to evaluate + arg := callFuncByName(&formulaFuncs{}, strings.NewReplacer( "_xlfn", "", ".", "").Replace(opfStack.Peek().(efp.Token).TValue), - []reflect.Value{reflect.ValueOf(argsList)}) + []reflect.Value{reflect.ValueOf(argsStack.Peek().(*list.List))}) if arg.Type == ArgError { return efp.Token{}, errors.New(arg.Value()) } - argsList.Init() + argsStack.Pop() opfStack.Pop() if opfStack.Len() > 0 { // still in function stack if nextToken.TType == efp.TokenTypeOperatorInfix { // mathematics calculate in formula function opfdStack.Push(efp.Token{TValue: arg.Value(), TType: efp.TokenTypeOperand, TSubType: efp.TokenSubTypeNumber}) } else { - argsList.PushBack(arg) + argsStack.Peek().(*list.List).PushBack(arg) } } else { opdStack.Push(efp.Token{TValue: arg.Value(), TType: efp.TokenTypeOperand, TSubType: efp.TokenSubTypeNumber}) @@ -1220,15 +1220,15 @@ func (fn *formulaFuncs) ATAN2(argsList *list.List) formulaArg { if argsList.Len() != 2 { return newErrorFormulaArg(formulaErrorVALUE, "ATAN2 requires 2 numeric arguments") } - x, err := strconv.ParseFloat(argsList.Back().Value.(formulaArg).String, 64) - if err != nil { - return newErrorFormulaArg(formulaErrorVALUE, err.Error()) + x := argsList.Back().Value.(formulaArg).ToNumber() + if x.Type == ArgError { + return x } - y, err := strconv.ParseFloat(argsList.Front().Value.(formulaArg).String, 64) - if err != nil { - return newErrorFormulaArg(formulaErrorVALUE, err.Error()) + y := argsList.Front().Value.(formulaArg).ToNumber() + if y.Type == ArgError { + return y } - return newNumberFormulaArg(math.Atan2(x, y)) + return newNumberFormulaArg(math.Atan2(x.Number, y.Number)) } // BASE function converts a number into a supplied base (radix), and returns a @@ -1243,16 +1243,17 @@ func (fn *formulaFuncs) BASE(argsList *list.List) formulaArg { if argsList.Len() > 3 { return newErrorFormulaArg(formulaErrorVALUE, "BASE allows at most 3 arguments") } - var number float64 - var radix, minLength int + var minLength int var err error - if number, err = strconv.ParseFloat(argsList.Front().Value.(formulaArg).String, 64); err != nil { - return newErrorFormulaArg(formulaErrorVALUE, err.Error()) + number := argsList.Front().Value.(formulaArg).ToNumber() + if number.Type == ArgError { + return number } - if radix, err = strconv.Atoi(argsList.Front().Next().Value.(formulaArg).String); err != nil { - return newErrorFormulaArg(formulaErrorVALUE, err.Error()) + radix := argsList.Front().Next().Value.(formulaArg).ToNumber() + if radix.Type == ArgError { + return radix } - if radix < 2 || radix > 36 { + if int(radix.Number) < 2 || int(radix.Number) > 36 { return newErrorFormulaArg(formulaErrorVALUE, "radix must be an integer >= 2 and <= 36") } if argsList.Len() > 2 { @@ -1260,7 +1261,7 @@ func (fn *formulaFuncs) BASE(argsList *list.List) formulaArg { return newErrorFormulaArg(formulaErrorVALUE, err.Error()) } } - result := strconv.FormatInt(int64(number), radix) + result := strconv.FormatInt(int64(number.Number), int(radix.Number)) if len(result) < minLength { result = strings.Repeat("0", minLength-len(result)) + result } @@ -1280,18 +1281,20 @@ func (fn *formulaFuncs) CEILING(argsList *list.List) formulaArg { return newErrorFormulaArg(formulaErrorVALUE, "CEILING allows at most 2 arguments") } number, significance, res := 0.0, 1.0, 0.0 - var err error - number, err = strconv.ParseFloat(argsList.Front().Value.(formulaArg).String, 64) - if err != nil { - return newErrorFormulaArg(formulaErrorVALUE, err.Error()) + n := argsList.Front().Value.(formulaArg).ToNumber() + if n.Type == ArgError { + return n } + number = n.Number if number < 0 { significance = -1 } if argsList.Len() > 1 { - if significance, err = strconv.ParseFloat(argsList.Back().Value.(formulaArg).String, 64); err != nil { - return newErrorFormulaArg(formulaErrorVALUE, err.Error()) + s := argsList.Back().Value.(formulaArg).ToNumber() + if s.Type == ArgError { + return s } + significance = s.Number } if significance < 0 && number > 0 { return newErrorFormulaArg(formulaErrorVALUE, "negative sig to CEILING invalid") @@ -1319,25 +1322,30 @@ func (fn *formulaFuncs) CEILINGMATH(argsList *list.List) formulaArg { return newErrorFormulaArg(formulaErrorVALUE, "CEILING.MATH allows at most 3 arguments") } number, significance, mode := 0.0, 1.0, 1.0 - var err error - if number, err = strconv.ParseFloat(argsList.Front().Value.(formulaArg).String, 64); err != nil { - return newErrorFormulaArg(formulaErrorVALUE, err.Error()) + n := argsList.Front().Value.(formulaArg).ToNumber() + if n.Type == ArgError { + return n } + number = n.Number if number < 0 { significance = -1 } if argsList.Len() > 1 { - if significance, err = strconv.ParseFloat(argsList.Front().Next().Value.(formulaArg).String, 64); err != nil { - return newErrorFormulaArg(formulaErrorVALUE, err.Error()) + s := argsList.Front().Next().Value.(formulaArg).ToNumber() + if s.Type == ArgError { + return s } + significance = s.Number } if argsList.Len() == 1 { return newNumberFormulaArg(math.Ceil(number)) } if argsList.Len() > 2 { - if mode, err = strconv.ParseFloat(argsList.Back().Value.(formulaArg).String, 64); err != nil { - return newErrorFormulaArg(formulaErrorVALUE, err.Error()) + m := argsList.Back().Value.(formulaArg).ToNumber() + if m.Type == ArgError { + return m } + mode = m.Number } val, res := math.Modf(number / significance) if res != 0 { @@ -1364,11 +1372,11 @@ func (fn *formulaFuncs) CEILINGPRECISE(argsList *list.List) formulaArg { return newErrorFormulaArg(formulaErrorVALUE, "CEILING.PRECISE allows at most 2 arguments") } number, significance := 0.0, 1.0 - var err error - number, err = strconv.ParseFloat(argsList.Front().Value.(formulaArg).String, 64) - if err != nil { - return newErrorFormulaArg(formulaErrorVALUE, err.Error()) + n := argsList.Front().Value.(formulaArg).ToNumber() + if n.Type == ArgError { + return n } + number = n.Number if number < 0 { significance = -1 } @@ -1376,13 +1384,14 @@ func (fn *formulaFuncs) CEILINGPRECISE(argsList *list.List) formulaArg { return newNumberFormulaArg(math.Ceil(number)) } if argsList.Len() > 1 { - if significance, err = strconv.ParseFloat(argsList.Back().Value.(formulaArg).String, 64); err != nil { - err = errors.New(formulaErrorVALUE) - return newErrorFormulaArg(formulaErrorVALUE, err.Error()) + s := argsList.Back().Value.(formulaArg).ToNumber() + if s.Type == ArgError { + return s } + significance = s.Number significance = math.Abs(significance) if significance == 0 { - return newStringFormulaArg("0") + return newNumberFormulaArg(significance) } } val, res := math.Modf(number / significance) @@ -1404,19 +1413,22 @@ func (fn *formulaFuncs) COMBIN(argsList *list.List) formulaArg { return newErrorFormulaArg(formulaErrorVALUE, "COMBIN requires 2 argument") } number, chosen, val := 0.0, 0.0, 1.0 - var err error - if number, err = strconv.ParseFloat(argsList.Front().Value.(formulaArg).String, 64); err != nil { - return newErrorFormulaArg(formulaErrorVALUE, err.Error()) + n := argsList.Front().Value.(formulaArg).ToNumber() + if n.Type == ArgError { + return n } - if chosen, err = strconv.ParseFloat(argsList.Back().Value.(formulaArg).String, 64); err != nil { - return newErrorFormulaArg(formulaErrorVALUE, err.Error()) + number = n.Number + c := argsList.Back().Value.(formulaArg).ToNumber() + if c.Type == ArgError { + return c } + chosen = c.Number number, chosen = math.Trunc(number), math.Trunc(chosen) if chosen > number { return newErrorFormulaArg(formulaErrorVALUE, "COMBIN requires number >= number_chosen") } if chosen == number || chosen == 0 { - return newStringFormulaArg("1") + return newNumberFormulaArg(1) } for c := float64(1); c <= chosen; c++ { val *= (number + 1 - c) / c @@ -1434,21 +1446,22 @@ func (fn *formulaFuncs) COMBINA(argsList *list.List) formulaArg { return newErrorFormulaArg(formulaErrorVALUE, "COMBINA requires 2 argument") } var number, chosen float64 - var err error - number, err = strconv.ParseFloat(argsList.Front().Value.(formulaArg).String, 64) - if err != nil { - return newErrorFormulaArg(formulaErrorVALUE, err.Error()) + n := argsList.Front().Value.(formulaArg).ToNumber() + if n.Type == ArgError { + return n } - chosen, err = strconv.ParseFloat(argsList.Back().Value.(formulaArg).String, 64) - if err != nil { - return newErrorFormulaArg(formulaErrorVALUE, err.Error()) + number = n.Number + c := argsList.Back().Value.(formulaArg).ToNumber() + if c.Type == ArgError { + return c } + chosen = c.Number number, chosen = math.Trunc(number), math.Trunc(chosen) if number < chosen { return newErrorFormulaArg(formulaErrorVALUE, "COMBINA requires number > number_chosen") } if number == 0 { - return newStringFormulaArg("0") + return newNumberFormulaArg(number) } args := list.New() args.PushBack(formulaArg{ @@ -1471,11 +1484,11 @@ func (fn *formulaFuncs) COS(argsList *list.List) formulaArg { if argsList.Len() != 1 { return newErrorFormulaArg(formulaErrorVALUE, "COS requires 1 numeric argument") } - val, err := strconv.ParseFloat(argsList.Front().Value.(formulaArg).String, 64) - if err != nil { - return newErrorFormulaArg(formulaErrorVALUE, err.Error()) + val := argsList.Front().Value.(formulaArg).ToNumber() + if val.Type == ArgError { + return val } - return newNumberFormulaArg(math.Cos(val)) + return newNumberFormulaArg(math.Cos(val.Number)) } // COSH function calculates the hyperbolic cosine (cosh) of a supplied number. @@ -1487,11 +1500,11 @@ func (fn *formulaFuncs) COSH(argsList *list.List) formulaArg { if argsList.Len() != 1 { return newErrorFormulaArg(formulaErrorVALUE, "COSH requires 1 numeric argument") } - val, err := strconv.ParseFloat(argsList.Front().Value.(formulaArg).String, 64) - if err != nil { - return newErrorFormulaArg(formulaErrorVALUE, err.Error()) + val := argsList.Front().Value.(formulaArg).ToNumber() + if val.Type == ArgError { + return val } - return newNumberFormulaArg(math.Cosh(val)) + return newNumberFormulaArg(math.Cosh(val.Number)) } // COT function calculates the cotangent of a given angle. The syntax of the @@ -1503,14 +1516,14 @@ func (fn *formulaFuncs) COT(argsList *list.List) formulaArg { if argsList.Len() != 1 { return newErrorFormulaArg(formulaErrorVALUE, "COT requires 1 numeric argument") } - val, err := strconv.ParseFloat(argsList.Front().Value.(formulaArg).String, 64) - if err != nil { - return newErrorFormulaArg(formulaErrorVALUE, err.Error()) + val := argsList.Front().Value.(formulaArg).ToNumber() + if val.Type == ArgError { + return val } - if val == 0 { + if val.Number == 0 { return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV) } - return newNumberFormulaArg(math.Tan(val)) + return newNumberFormulaArg(1 / math.Tan(val.Number)) } // COTH function calculates the hyperbolic cotangent (coth) of a supplied @@ -1522,14 +1535,14 @@ func (fn *formulaFuncs) COTH(argsList *list.List) formulaArg { if argsList.Len() != 1 { return newErrorFormulaArg(formulaErrorVALUE, "COTH requires 1 numeric argument") } - val, err := strconv.ParseFloat(argsList.Front().Value.(formulaArg).String, 64) - if err != nil { - return newErrorFormulaArg(formulaErrorVALUE, err.Error()) + val := argsList.Front().Value.(formulaArg).ToNumber() + if val.Type == ArgError { + return val } - if val == 0 { + if val.Number == 0 { return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV) } - return newNumberFormulaArg(math.Tanh(val)) + return newNumberFormulaArg((math.Exp(val.Number) + math.Exp(-val.Number)) / (math.Exp(val.Number) - math.Exp(-val.Number))) } // CSC function calculates the cosecant of a given angle. The syntax of the @@ -1541,14 +1554,14 @@ func (fn *formulaFuncs) CSC(argsList *list.List) formulaArg { if argsList.Len() != 1 { return newErrorFormulaArg(formulaErrorVALUE, "CSC requires 1 numeric argument") } - val, err := strconv.ParseFloat(argsList.Front().Value.(formulaArg).String, 64) - if err != nil { - return newErrorFormulaArg(formulaErrorVALUE, err.Error()) + val := argsList.Front().Value.(formulaArg).ToNumber() + if val.Type == ArgError { + return val } - if val == 0 { + if val.Number == 0 { return newErrorFormulaArg(formulaErrorDIV, formulaErrorDIV) } - return newNumberFormulaArg(1 / math.Sin(val)) + return newNumberFormulaArg(1 / math.Sin(val.Number)) } // CSCH function calculates the hyperbolic cosecant (csch) of a supplied diff --git a/calc_test.go b/calc_test.go index ad3366ea..d0b1c64f 100644 --- a/calc_test.go +++ b/calc_test.go @@ -97,72 +97,84 @@ func TestCalcCellValue(t *testing.T) { "=ATANH(0.5)": "0.549306144334055", "=ATANH(ATANH(0))": "0", // ATAN2 - "=ATAN2(1,1)": "0.785398163397448", - "=ATAN2(1,-1)": "-0.785398163397448", - "=ATAN2(4,0)": "0", + "=ATAN2(1,1)": "0.785398163397448", + "=ATAN2(1,-1)": "-0.785398163397448", + "=ATAN2(4,0)": "0", + "=ATAN2(4,ATAN2(4,0))": "0", // BASE - "=BASE(12,2)": "1100", - "=BASE(12,2,8)": "00001100", - "=BASE(100000,16)": "186A0", + "=BASE(12,2)": "1100", + "=BASE(12,2,8)": "00001100", + "=BASE(100000,16)": "186A0", + "=BASE(BASE(12,2),16)": "44C", // CEILING - "=CEILING(22.25,0.1)": "22.3", - "=CEILING(22.25,0.5)": "22.5", - "=CEILING(22.25,1)": "23", - "=CEILING(22.25,10)": "30", - "=CEILING(22.25,20)": "40", - "=CEILING(-22.25,-0.1)": "-22.3", - "=CEILING(-22.25,-1)": "-23", - "=CEILING(-22.25,-5)": "-25", - "=CEILING(22.25)": "23", + "=CEILING(22.25,0.1)": "22.3", + "=CEILING(22.25,0.5)": "22.5", + "=CEILING(22.25,1)": "23", + "=CEILING(22.25,10)": "30", + "=CEILING(22.25,20)": "40", + "=CEILING(-22.25,-0.1)": "-22.3", + "=CEILING(-22.25,-1)": "-23", + "=CEILING(-22.25,-5)": "-25", + "=CEILING(22.25)": "23", + "=CEILING(CEILING(22.25,0.1),0.1)": "22.3", // _xlfn.CEILING.MATH - "=_xlfn.CEILING.MATH(15.25,1)": "16", - "=_xlfn.CEILING.MATH(15.25,0.1)": "15.3", - "=_xlfn.CEILING.MATH(15.25,5)": "20", - "=_xlfn.CEILING.MATH(-15.25,1)": "-15", - "=_xlfn.CEILING.MATH(-15.25,1,1)": "-15", // should be 16 - "=_xlfn.CEILING.MATH(-15.25,10)": "-10", - "=_xlfn.CEILING.MATH(-15.25)": "-15", - "=_xlfn.CEILING.MATH(-15.25,-5,-1)": "-10", + "=_xlfn.CEILING.MATH(15.25,1)": "16", + "=_xlfn.CEILING.MATH(15.25,0.1)": "15.3", + "=_xlfn.CEILING.MATH(15.25,5)": "20", + "=_xlfn.CEILING.MATH(-15.25,1)": "-15", + "=_xlfn.CEILING.MATH(-15.25,1,1)": "-15", // should be 16 + "=_xlfn.CEILING.MATH(-15.25,10)": "-10", + "=_xlfn.CEILING.MATH(-15.25)": "-15", + "=_xlfn.CEILING.MATH(-15.25,-5,-1)": "-10", + "=_xlfn.CEILING.MATH(_xlfn.CEILING.MATH(15.25,1),1)": "16", // _xlfn.CEILING.PRECISE - "=_xlfn.CEILING.PRECISE(22.25,0.1)": "22.3", - "=_xlfn.CEILING.PRECISE(22.25,0.5)": "22.5", - "=_xlfn.CEILING.PRECISE(22.25,1)": "23", - "=_xlfn.CEILING.PRECISE(22.25)": "23", - "=_xlfn.CEILING.PRECISE(22.25,10)": "30", - "=_xlfn.CEILING.PRECISE(22.25,0)": "0", - "=_xlfn.CEILING.PRECISE(-22.25,1)": "-22", - "=_xlfn.CEILING.PRECISE(-22.25,-1)": "-22", - "=_xlfn.CEILING.PRECISE(-22.25,5)": "-20", + "=_xlfn.CEILING.PRECISE(22.25,0.1)": "22.3", + "=_xlfn.CEILING.PRECISE(22.25,0.5)": "22.5", + "=_xlfn.CEILING.PRECISE(22.25,1)": "23", + "=_xlfn.CEILING.PRECISE(22.25)": "23", + "=_xlfn.CEILING.PRECISE(22.25,10)": "30", + "=_xlfn.CEILING.PRECISE(22.25,0)": "0", + "=_xlfn.CEILING.PRECISE(-22.25,1)": "-22", + "=_xlfn.CEILING.PRECISE(-22.25,-1)": "-22", + "=_xlfn.CEILING.PRECISE(-22.25,5)": "-20", + "=_xlfn.CEILING.PRECISE(_xlfn.CEILING.PRECISE(22.25,0.1),5)": "25", // COMBIN - "=COMBIN(6,1)": "6", - "=COMBIN(6,2)": "15", - "=COMBIN(6,3)": "20", - "=COMBIN(6,4)": "15", - "=COMBIN(6,5)": "6", - "=COMBIN(6,6)": "1", - "=COMBIN(0,0)": "1", + "=COMBIN(6,1)": "6", + "=COMBIN(6,2)": "15", + "=COMBIN(6,3)": "20", + "=COMBIN(6,4)": "15", + "=COMBIN(6,5)": "6", + "=COMBIN(6,6)": "1", + "=COMBIN(0,0)": "1", + "=COMBIN(6,COMBIN(0,0))": "6", // _xlfn.COMBINA - "=_xlfn.COMBINA(6,1)": "6", - "=_xlfn.COMBINA(6,2)": "21", - "=_xlfn.COMBINA(6,3)": "56", - "=_xlfn.COMBINA(6,4)": "126", - "=_xlfn.COMBINA(6,5)": "252", - "=_xlfn.COMBINA(6,6)": "462", - "=_xlfn.COMBINA(0,0)": "0", + "=_xlfn.COMBINA(6,1)": "6", + "=_xlfn.COMBINA(6,2)": "21", + "=_xlfn.COMBINA(6,3)": "56", + "=_xlfn.COMBINA(6,4)": "126", + "=_xlfn.COMBINA(6,5)": "252", + "=_xlfn.COMBINA(6,6)": "462", + "=_xlfn.COMBINA(0,0)": "0", + "=_xlfn.COMBINA(0,_xlfn.COMBINA(0,0))": "0", // COS "=COS(0.785398163)": "0.707106781467586", "=COS(0)": "1", + "=COS(COS(0))": "0.54030230586814", // COSH - "=COSH(0)": "1", - "=COSH(0.5)": "1.127625965206381", - "=COSH(-2)": "3.762195691083632", + "=COSH(0)": "1", + "=COSH(0.5)": "1.127625965206381", + "=COSH(-2)": "3.762195691083632", + "=COSH(COSH(0))": "1.543080634815244", // _xlfn.COT - "=_xlfn.COT(0.785398163397448)": "0.999999999999999", + "=_xlfn.COT(0.785398163397448)": "1.000000000000001", + "=_xlfn.COT(_xlfn.COT(0.45))": "-0.545473116787229", // _xlfn.COTH - "=_xlfn.COTH(-3.14159265358979)": "-0.99627207622075", + "=_xlfn.COTH(-3.14159265358979)": "-1.003741873197322", + "=_xlfn.COTH(_xlfn.COTH(1))": "1.156014018113954", // _xlfn.CSC "=_xlfn.CSC(-6)": "3.578899547254406", "=_xlfn.CSC(1.5707963267949)": "1", + "=_xlfn.CSC(_xlfn.CSC(1))": "1.077851840310882", // _xlfn.CSCH "=_xlfn.CSCH(-3.14159265358979)": "-0.086589537530047", // _xlfn.DECIMAL @@ -558,7 +570,7 @@ func TestCalcCellValue(t *testing.T) { "=BASE(1,2,3,4)": "BASE allows at most 3 arguments", "=BASE(1,1)": "radix must be an integer >= 2 and <= 36", `=BASE("X",2)`: "strconv.ParseFloat: parsing \"X\": invalid syntax", - `=BASE(1,"X")`: "strconv.Atoi: parsing \"X\": invalid syntax", + `=BASE(1,"X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax", `=BASE(1,2,"X")`: "strconv.Atoi: parsing \"X\": invalid syntax", // CEILING "=CEILING()": "CEILING requires at least 1 argument", @@ -576,7 +588,7 @@ func TestCalcCellValue(t *testing.T) { "=_xlfn.CEILING.PRECISE()": "CEILING.PRECISE requires at least 1 argument", "=_xlfn.CEILING.PRECISE(1,2,3)": "CEILING.PRECISE allows at most 2 arguments", `=_xlfn.CEILING.PRECISE("X",2)`: "strconv.ParseFloat: parsing \"X\": invalid syntax", - `=_xlfn.CEILING.PRECISE(1,"X")`: "#VALUE!", + `=_xlfn.CEILING.PRECISE(1,"X")`: "strconv.ParseFloat: parsing \"X\": invalid syntax", // COMBIN "=COMBIN()": "COMBIN requires 2 argument", "=COMBIN(-1,1)": "COMBIN requires number >= number_chosen", @@ -1009,7 +1021,7 @@ func TestAND(t *testing.T) { }) fn := formulaFuncs{} result := fn.AND(argsList) - assert.Equal(t, result.String, "TRUE") + assert.Equal(t, result.String, "") assert.Empty(t, result.Error) }