Golang中的返回类型可以是int、float或complex。

huangapple go评论85阅读模式
英文:

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&lt;0{
     return complex, nil
   }
   if a&gt;=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 &lt; 0 {
		r, j := 1.0, 2.0
		return complex(r, j), nil
	}
	if a &gt;= 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(&quot;\treal:&quot;, real(c))
}

c, err = abcd(-1, 0, 0, 0)
fmt.Println(c, err)
if imag(c) == 0 {
	fmt.Println(&quot;\treal:&quot;, real(c))
}

Which outputs (try it on the Go Playground):

(3+0i) &lt;nil&gt;
	real: 3
(1+2i) &lt;nil&gt;

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 &lt; 0 {
		r, j := 1.0, 2.0
		return complex(r, j), true, nil
	}
	if a &gt;= 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(&quot;\treal:&quot;, real(c))
}

c, isC, err = abcd(-1, 0, 0, 0)
fmt.Println(c, err)
if !isC {
	fmt.Println(&quot;\treal:&quot;, 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 &lt; 0 {
		r, j := 1.0, 2.0
		x = :complex(r, j)
		return &amp;x, nil, nil
	}
	if a &gt;= 0 {
		f := 3.0
		return nil, &amp;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(&quot;\tcmplx:&quot;, *c)
}
if f != nil {
	fmt.Println(&quot;\treal:&quot;, *f)
}

c, f, err = abcd(-1, 0, 0, 0)
fmt.Println(c, f, err)
if c != nil {
	fmt.Println(&quot;\tcmplx:&quot;, *c)
}
if f != nil {
	fmt.Println(&quot;\treal:&quot;, *f)
}

Output (try it on the Go Playground):

&lt;nil&gt; 0xc000018050 &lt;nil&gt;
	real: 3
0xc000018070 &lt;nil&gt; &lt;nil&gt;
	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.

huangapple
  • 本文由 发表于 2021年7月4日 20:07:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/68244572.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定