复数
Go 语言提供了两种精度的复数类型:complex64
和 complex128
,分别对应 float32
和 float64
两种浮点数精度。内置的 complex
函数用于构建复数,内建的 real
和 imag
函数分别返回复数的实部和虚部:
var x complex128 = complex(1, 2) // 1+2i
var y complex128 = complex(3, 4) // 3+4i
fmt.Println(x*y) // "(-5+10i)"
fmt.Println(real(x*y)) // "-5"
fmt.Println(imag(x*y)) // "10"
如果一个浮点数面值或一个十进制整数面值后面跟着一个 i ,例如 3.141592i 或 2i ,它将构成一个复数的虚部,复数的实部是 0 :
fmt.Println(1i * 1i) // "(-1+0i)", i^2 = -1
在常量算术规则下,一个复数常量可以加到另一个普通数值常量(整数或浮点数、实部或虚部),我们可以用自然的方式书写复数,就像 1+2i
或与之等价的写法 2i+1
。上面 x 和 y 的声明语句还可以简化:
x := 1 + 2i
y := 3 + 4i
复数也可以用 ==
和 !=
进行相等比较。只有两个复数的实部和虚部都相等的时候它们才是相等的(译注:浮点数的相等比较是危险的,需要特别小心处理精度问题)。
math/cmplx
包提供了复数处理的许多函数,例如求复数的平方根函数和求幂函数。
fmt.Println(cmplx.Sqrt(-1)) // "(0+1i)"
下面的程序使用 complex128 复数算法来生成一个 Mandelbrot 图像。
Unresolved include directive in modules/ROOT/pages/ch3/ch3-03.adoc - include::example$/ch3/mandelbrot/main.go[]
用于遍历 1024x1024 图像每个点的两个嵌套的循环对应 -2 到 +2 区间的复数平面。程序反复测试每个点对应复数值平方值加一个增量值对应的点是否超出半径为 2 的圆。如果超过了,通过根据预设置的逃逸迭代次数对应的灰度颜色来代替。如果不是,那么该点属于 Mandelbrot 集合,使用黑色颜色标记。最终程序将生成的 PNG 格式分形图像输出到标准输出,如图3.3所示。

练习 3.5: 实现一个彩色的 Mandelbrot 图像,使用 image.NewRGBA 创建图像,使用 color.RGBA 或 color.YCbCr 生成颜色。
练习 3.6: 升采样技术可以降低每个像素对计算颜色值和平均值的影响。简单的方法是将每个像素分成四个子像素,实现它。
练习 3.7: 另一个生成分形图像的方式是使用牛顿法来求解一个复数方程,例如 z4-1=0。每个起点到四个根的迭代次数对应阴影的灰度。方程根对应的点用颜色表示。
练习 3.8: 通过提高精度来生成更多级别的分形。使用四种不同精度类型的数字实现相同的分形:complex64、complex128、big.Float 和 big.Rat 。(后面两种类型在 math/big 包声明。Float 是有指定限精度的浮点数;Rat 是无限精度的有理数。)它们间的性能和内存使用对比如何?当渲染图可见时缩放的级别是多少?
练习 3.9: 编写一个 web 服务器,用于给客户端生成分形的图像。运行客户端通过 HTTP 参数指定 x 、y 和 zoom 参数。