diff options
Diffstat (limited to 'calc.go')
-rw-r--r-- | calc.go | 206 |
1 files changed, 203 insertions, 3 deletions
@@ -7,7 +7,7 @@ // spreadsheet documents generated by Microsoft Excelâ„¢ 2007 and later. Supports // complex components by high compatibility, and provided streaming API for // generating or reading data from a worksheet with huge amounts of data. This -// library needs Go version 1.10 or later. +// library needs Go version 1.15 or later. package excelize @@ -17,6 +17,7 @@ import ( "errors" "fmt" "math" + "math/cmplx" "math/rand" "net/url" "reflect" @@ -292,6 +293,15 @@ var tokenPriority = map[string]int{ // HLOOKUP // IF // IFERROR +// IMABS +// IMCOS +// IMCOSH +// IMCOT +// IMCSC +// IMCSCH +// IMEXP +// IMLN +// IMLOG10 // INT // ISBLANK // ISERR @@ -1475,8 +1485,38 @@ func (fn *formulaFuncs) COMPLEX(argsList *list.List) formulaArg { return newErrorFormulaArg(formulaErrorVALUE, formulaErrorVALUE) } } - r := strings.NewReplacer("(", "", ")", "", "0+", "", "+0i", "", "0+0i", "0", "i", suffix) - return newStringFormulaArg(r.Replace(fmt.Sprint(complex(real.Number, i.Number)))) + return newStringFormulaArg(cmplx2str(fmt.Sprint(complex(real.Number, i.Number)), suffix)) +} + +// cmplx2str replace complex number string characters. +func cmplx2str(c, suffix string) string { + if c == "(0+0i)" || c == "(0-0i)" { + return "0" + } + c = strings.TrimPrefix(c, "(") + c = strings.TrimPrefix(c, "+0+") + c = strings.TrimPrefix(c, "-0+") + c = strings.TrimSuffix(c, ")") + c = strings.TrimPrefix(c, "0+") + if strings.HasPrefix(c, "0-") { + c = "-" + strings.TrimPrefix(c, "0-") + } + c = strings.TrimPrefix(c, "0+") + c = strings.TrimSuffix(c, "+0i") + c = strings.TrimSuffix(c, "-0i") + c = strings.NewReplacer("+1i", "i", "-1i", "-i").Replace(c) + c = strings.Replace(c, "i", suffix, -1) + return c +} + +// str2cmplx convert complex number string characters. +func str2cmplx(c string) string { + c = strings.Replace(c, "j", "i", -1) + if c == "i" { + c = "1i" + } + c = strings.NewReplacer("+i", "+1i", "-i", "-1i").Replace(c) + return c } // DEC2BIN function converts a decimal number into a Binary (Base 2) number. @@ -1651,6 +1691,166 @@ func (fn *formulaFuncs) hex2dec(number string) formulaArg { return newNumberFormulaArg(decimal) } +// IMABS function returns the absolute value (the modulus) of a complex +// number. The syntax of the function is: +// +// IMABS(inumber) +// +func (fn *formulaFuncs) IMABS(argsList *list.List) formulaArg { + if argsList.Len() != 1 { + return newErrorFormulaArg(formulaErrorVALUE, "IMABS requires 1 argument") + } + inumber, err := strconv.ParseComplex(strings.Replace(argsList.Front().Value.(formulaArg).Value(), "j", "i", -1), 128) + if err != nil { + return newErrorFormulaArg(formulaErrorNUM, err.Error()) + } + return newNumberFormulaArg(cmplx.Abs(inumber)) +} + +// IMCOS function returns the cosine of a supplied complex number. The syntax +// of the function is: +// +// IMCOS(inumber) +// +func (fn *formulaFuncs) IMCOS(argsList *list.List) formulaArg { + if argsList.Len() != 1 { + return newErrorFormulaArg(formulaErrorVALUE, "IMCOS requires 1 argument") + } + inumber, err := strconv.ParseComplex(strings.Replace(argsList.Front().Value.(formulaArg).Value(), "j", "i", -1), 128) + if err != nil { + return newErrorFormulaArg(formulaErrorNUM, err.Error()) + } + return newStringFormulaArg(cmplx2str(fmt.Sprint(cmplx.Cos(inumber)), "i")) +} + +// IMCOSH function returns the hyperbolic cosine of a supplied complex number. The syntax +// of the function is: +// +// IMCOSH(inumber) +// +func (fn *formulaFuncs) IMCOSH(argsList *list.List) formulaArg { + if argsList.Len() != 1 { + return newErrorFormulaArg(formulaErrorVALUE, "IMCOSH requires 1 argument") + } + inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128) + if err != nil { + return newErrorFormulaArg(formulaErrorNUM, err.Error()) + } + return newStringFormulaArg(cmplx2str(fmt.Sprint(cmplx.Cosh(inumber)), "i")) +} + +// IMCOT function returns the cotangent of a supplied complex number. The syntax +// of the function is: +// +// IMCOT(inumber) +// +func (fn *formulaFuncs) IMCOT(argsList *list.List) formulaArg { + if argsList.Len() != 1 { + return newErrorFormulaArg(formulaErrorVALUE, "IMCOT requires 1 argument") + } + inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128) + if err != nil { + return newErrorFormulaArg(formulaErrorNUM, err.Error()) + } + return newStringFormulaArg(cmplx2str(fmt.Sprint(cmplx.Cot(inumber)), "i")) +} + +// IMCSC function returns the cosecant of a supplied complex number. The syntax +// of the function is: +// +// IMCSC(inumber) +// +func (fn *formulaFuncs) IMCSC(argsList *list.List) formulaArg { + if argsList.Len() != 1 { + return newErrorFormulaArg(formulaErrorVALUE, "IMCSC requires 1 argument") + } + inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128) + if err != nil { + return newErrorFormulaArg(formulaErrorNUM, err.Error()) + } + num := 1 / cmplx.Sin(inumber) + if cmplx.IsInf(num) { + return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM) + } + return newStringFormulaArg(cmplx2str(fmt.Sprint(num), "i")) +} + +// IMCSCH function returns the hyperbolic cosecant of a supplied complex +// number. The syntax of the function is: +// +// IMCSCH(inumber) +// +func (fn *formulaFuncs) IMCSCH(argsList *list.List) formulaArg { + if argsList.Len() != 1 { + return newErrorFormulaArg(formulaErrorVALUE, "IMCSCH requires 1 argument") + } + inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128) + if err != nil { + return newErrorFormulaArg(formulaErrorNUM, err.Error()) + } + num := 1 / cmplx.Sinh(inumber) + if cmplx.IsInf(num) { + return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM) + } + return newStringFormulaArg(cmplx2str(fmt.Sprint(num), "i")) +} + +// IMEXP function returns the exponential of a supplied complex number. The +// syntax of the function is: +// +// IMEXP(inumber) +// +func (fn *formulaFuncs) IMEXP(argsList *list.List) formulaArg { + if argsList.Len() != 1 { + return newErrorFormulaArg(formulaErrorVALUE, "IMEXP requires 1 argument") + } + inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128) + if err != nil { + return newErrorFormulaArg(formulaErrorNUM, err.Error()) + } + return newStringFormulaArg(cmplx2str(fmt.Sprint(cmplx.Exp(inumber)), "i")) +} + +// IMLN function returns the natural logarithm of a supplied complex number. +// The syntax of the function is: +// +// IMLN(inumber) +// +func (fn *formulaFuncs) IMLN(argsList *list.List) formulaArg { + if argsList.Len() != 1 { + return newErrorFormulaArg(formulaErrorVALUE, "IMLN requires 1 argument") + } + inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128) + if err != nil { + return newErrorFormulaArg(formulaErrorNUM, err.Error()) + } + num := cmplx.Log(inumber) + if cmplx.IsInf(num) { + return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM) + } + return newStringFormulaArg(cmplx2str(fmt.Sprint(num), "i")) +} + +// IMLOG10 function returns the common (base 10) logarithm of a supplied +// complex number. The syntax of the function is: +// +// IMLOG10(inumber) +// +func (fn *formulaFuncs) IMLOG10(argsList *list.List) formulaArg { + if argsList.Len() != 1 { + return newErrorFormulaArg(formulaErrorVALUE, "IMLOG10 requires 1 argument") + } + inumber, err := strconv.ParseComplex(str2cmplx(argsList.Front().Value.(formulaArg).Value()), 128) + if err != nil { + return newErrorFormulaArg(formulaErrorNUM, err.Error()) + } + num := cmplx.Log10(inumber) + if cmplx.IsInf(num) { + return newErrorFormulaArg(formulaErrorNUM, formulaErrorNUM) + } + return newStringFormulaArg(cmplx2str(fmt.Sprint(num), "i")) +} + // OCT2BIN function converts an Octal (Base 8) number into a Binary (Base 2) // number. The syntax of the function is: // |