英文:
Golang return or float or complex
问题
我正在尝试编写一个三次方程求解器。
func solveCubicEquation(a, b, c, d float64) (returnType, err) {
if a < 0 {
return complex, nil
}
if a >= 0 {
return float64, nil
}
}
有没有一种方法可以返回一个接口或其他东西来管理这种行为?
英文:
I'm trying to write a cubic equation solver.
func (a,b,c,d float64) (returnType,err){
if a<0{
return complex, nil
}
if a>=0 {
return float64, nil
}
}
Is there a way to return and interface or something to manage this behavior?
答案1
得分: 6
由于实数(浮点数)是复数的一个子集,您可以选择始终返回一个复数,对于只返回float64
的情况,将虚部保留为0
:
func abcd(a, b, c, d float64) (complex128, error) {
if a < 0 {
r, j := 1.0, 2.0
return complex(r, j), nil
}
if a >= 0 {
r := 3.0
return complex(r, 0), nil
}
return 0 + 0i, nil
}
测试一下:
c, err := abcd(1, 0, 0, 0)
fmt.Println(c, err)
if imag(c) == 0 {
fmt.Println("\treal:", real(c))
}
c, err = abcd(-1, 0, 0, 0)
fmt.Println(c, err)
if imag(c) == 0 {
fmt.Println("\treal:", real(c))
}
输出结果为(在Go Playground上尝试):
(3+0i) <nil>
real: 3
(1+2i) <nil>
是的,如果返回的复数的虚部为0
,您无法区分这种特殊情况和仅返回实数的情况。也许您不需要区分它们?如果不需要,这不是一个问题。如果您确实需要区分它们,您还可以返回第三个值,告诉结果是否实际上是一个复数:
func abcd(a, b, c, d float64) (x complex128, isComplex bool, err error) {
if a < 0 {
r, j := 1.0, 2.0
return complex(r, j), true, nil
}
if a >= 0 {
r := 3.0
return complex(r, 0), false, nil
}
return 0 + 0i, false, nil
}
测试一下:
c, isC, err := abcd(1, 0, 0, 0)
fmt.Println(c, isC, err)
if !isC {
fmt.Println("\treal:", real(c))
}
c, isC, err = abcd(-1, 0, 0, 0)
fmt.Println(c, err)
if !isC {
fmt.Println("\treal:", real(c))
}
输出结果相同。在Go Playground上尝试这个。
上述解决方案之所以可行,是因为实数是复数的一个子集。在一般情况下,您可以使用多个返回值,每个返回值都是一个指针,并且您可以检查哪个返回值不为nil
。类似这样:
func abcd(a, b, c, d float64) (*complex128, *float64, error) {
if a < 0 {
r, j := 1.0, 2.0
x := complex(r, j)
return &x, nil, nil
}
if a >= 0 {
f := 3.0
return nil, &f, nil
}
return nil, nil, nil
}
测试一下:
c, f, err := abcd(1, 0, 0, 0)
fmt.Println(c, f, err)
if c != nil {
fmt.Println("\tcmplx:", *c)
}
if f != nil {
fmt.Println("\treal:", *f)
}
c, f, err = abcd(-1, 0, 0, 0)
fmt.Println(c, f, err)
if c != nil {
fmt.Println("\tcmplx:", *c)
}
if f != nil {
fmt.Println("\treal:", *f)
}
输出结果为(在Go Playground上尝试):
<nil> 0xc000018050 <nil>
real: 3
0xc000018070 <nil> <nil>
cmplx: (1+2i)
您还可以将最后两个解决方案结合起来:您可以返回非指针和一个isComplex
标志,告诉哪个返回值是有效的。
英文:
Since real numbers (floats) are a subset of complex numbers, you may opt to always return a complex number, and where you would only return float64
, you leave the imaginary part 0
:
func abcd(a, b, c, d float64) (complex128, error) {
if a < 0 {
r, j := 1.0, 2.0
return complex(r, j), nil
}
if a >= 0 {
r := 3.0
return complex(r, 0), nil
}
return 0 + 0i, nil
}
Testing it:
c, err := abcd(1, 0, 0, 0)
fmt.Println(c, err)
if imag(c) == 0 {
fmt.Println("\treal:", real(c))
}
c, err = abcd(-1, 0, 0, 0)
fmt.Println(c, err)
if imag(c) == 0 {
fmt.Println("\treal:", real(c))
}
Which outputs (try it on the Go Playground):
(3+0i) <nil>
real: 3
(1+2i) <nil>
Yes, if a complex number would be returned whose imaginary part is 0
, you can't distinguish this special case from the case where only a real number would be returned. Maybe you don't have to? If not, it's not a problem. If you do need to differentiate them, you may also return a 3rd value telling if the result is in fact a complex number:
func abcd(a, b, c, d float64) (x complex128, isComplex bool, err error) {
if a < 0 {
r, j := 1.0, 2.0
return complex(r, j), true, nil
}
if a >= 0 {
r := 3.0
return complex(r, 0), false, nil
}
return 0 + 0i, false, nil
}
Testing it:
c, isC, err := abcd(1, 0, 0, 0)
fmt.Println(c, isC, err)
if !isC {
fmt.Println("\treal:", real(c))
}
c, isC, err = abcd(-1, 0, 0, 0)
fmt.Println(c, err)
if !isC {
fmt.Println("\treal:", real(c))
}
Output is the same. Try this one on the Go Playground.
The above solutions are possible because real numbers are a subset of complex numbers. In the general case you may use multiple return values, each being a pointer, and you may check which return value is not nil
. Something like this:
func abcd(a, b, c, d float64) (*complex128, *float64, error) {
if a < 0 {
r, j := 1.0, 2.0
x = :complex(r, j)
return &x, nil, nil
}
if a >= 0 {
f := 3.0
return nil, &f, nil
}
return nil, nil, nil
}
Testing it:
c, f, err := abcd(1, 0, 0, 0)
fmt.Println(c, f, err)
if c != nil {
fmt.Println("\tcmplx:", *c)
}
if f != nil {
fmt.Println("\treal:", *f)
}
c, f, err = abcd(-1, 0, 0, 0)
fmt.Println(c, f, err)
if c != nil {
fmt.Println("\tcmplx:", *c)
}
if f != nil {
fmt.Println("\treal:", *f)
}
Output (try it on the Go Playground):
<nil> 0xc000018050 <nil>
real: 3
0xc000018070 <nil> <nil>
cmplx: (1+2i)
And you could also combine the last 2 solutions: you could return non-pointers and an isComplex
flag telling which return value is valid.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论