Go語言核心之美 2.2-浮點數

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

Go提供了兩種size的浮點數,float32和float64。它們的算術規範是由IEEE754國際標準定義,現代CPU都實現了這個規範。

浮點數能夠表示的範圍可以從很小到很巨大,這個極限值範圍可以在math包中擷取,math.MaxFloat32表示float32的最大值,大約是3.4e38,math.MaxFloat64大約是1.8e308,兩個類型最小的非負值大約是1.4e-45和4.9e-324。

float32大約可以提供小數點後6位的精度,作為對比,float64可以提供小數點後15位的精度。通常情況應該優先選擇float64,因此float32的精確度較低,在累積計算時誤差擴散很快,而且float32能精確表達的最小正整數並不大,因為浮點數和整數的底層解釋方式完全不同,具體見IEEE754詳解。

var f float32 = 16777216 // 1 << 24fmt.Println(f == f+1)    // "true"!

浮點數字面量可以使用十進位數字表示:

const e = 2.71828 // (非精確值)
小數點前面或者後面的數字都可以省略,例如:.707 , 1.   ,對於那種很小或者很大的數值最好用科學計數法,在指數前加上e或者E:
const Avogadro = 6.02214129e23  // 阿伏伽德羅常數const Planck   = 6.62606957e-34 // 普朗克常數
fmt列印浮點數時,若使用%g參數,會採用更高的精度更緊湊的表現形式進行列印,但是在列印表格式資料時,%e(指數)或者%f(非指數的)的形式可能更合適,上面三個參數都可以控制列印的寬度和精度:
for x := 0; x < 8; x++ {    fmt.Printf("x = %d e^x = %8.3f\n", x, math.Exp(float64(x)))}
上面的代碼使用了小數點後3位的精度進行列印,列印寬度是8個字元:
x = 0   ex =    1.000x = 1   ex =    2.718x = 2   ex =    7.389x = 3   ex =   20.086x = 4   ex =   54.598x = 5   ex =  148.413x = 6   ex =  403.429x = 7   ex = 1096.633

math包不僅包含了大量的數學函數,還包含了IEEE754規範下特殊浮點數的建立和查看:正無窮,表明數字太大溢出的情況;負無窮,表示被0除的結果;NaN(不是一個數值),用來表示無效運算的結果,例如 0 / 0, math.Sqrt(-1)。

var z float64fmt.Println(z, -z, 1/z, -1/z, z/z) //  "0 -0 +Inf -Inf NaN"

函數math.IsNaN測試一個數值是否是NaN,math.NaN會返回一個NaN值。雖然可以在數值計算中用NaN做為一個哨兵值,但是測試一個計算的結果是否等於NaN是很危險的,因為任何值跟NaN比較的結果都是false:

nan := math.NaN()fmt.Println(nan == nan, nan < nan, nan > nan) // "false false false"
如果一個返回浮點數的函數可能失敗,那最好還是單獨的報告失敗:
func compute() (value float64, ok bool) {    // ...    if failed {        return 0, false    }    return result, true}
下面的程式示範了通過浮點數計算來產生圖形,使用了z = f(x,y)來進行三維建模,使用了SVG格式做映像輸出,SVG是一個用於繪製向量線的XML標準。展示了sin(r)/r函數產生的圖形,r = sqrt(x*x + y*y):



// Surface computes an SVG rendering of a 3-D surface function.package mainimport (    "fmt"    "math")const (    width, height = 600, 320            // canvas size in pixels    cells         = 100                 // number of grid cells    xyrange       = 30.0                // axis ranges (-xyrange..+xyrange)    xyscale       = width / 2 / xyrange // pixels per x or y unit    zscale        = height * 0.4        // pixels per z unit    angle         = math.Pi / 6         // angle of x, y axes (=30°))var sin30, cos30 = math.Sin(angle), math.Cos(angle) // sin(30°), cos(30°)func main() {    fmt.Printf("<svg xmlns='http://www.w3.org/2000/svg' "+        "style='stroke: grey; fill: white; stroke-width: 0.7' "+        "width='%d' height='%d'>", width, height)    for i := 0; i < cells; i++ {        for j := 0; j < cells; j++ {            ax, ay := corner(i+1, j)            bx, by := corner(i, j)            cx, cy := corner(i, j+1)            dx, dy := corner(i+1, j+1)            fmt.Printf("<polygon points='%g,%g %g,%g %g,%g %g,%g'/>\n",                ax, ay, bx, by, cx, cy, dx, dy)        }    }    fmt.Println("</svg>")}func corner(i, j int) (float64, float64) {    // Find point (x,y) at corner of cell (i,j).    x := xyrange * (float64(i)/cells - 0.5)    y := xyrange * (float64(j)/cells - 0.5)    // Compute surface height z.    z := f(x, y)    // Project (x,y,z) isometrically onto 2-D SVG canvas (sx,sy).    sx := width/2 + (x-y)*cos30*xyscale    sy := height/2 + (x+y)*sin30*xyscale - z*zscale    return sx, sy}func f(x, y float64) float64 {    r := math.Hypot(x, y) // distance from (0,0)    return math.Sin(r) / r}
corner函數返回兩個值,分別是網格頂點的x,y座標。
如果要深入解釋映像產生的原理,我們還需要一些幾何學知識。但是這裡會跳過這些幾何學原理,畢竟這個程式主要是為了示範浮點數的運算。程式本質上是三個座標系間的映射,如所示,第一個是100*100的二維網格,每個儲存格都有座標(i,j),從座標系原點(0,0)開始延伸。繪製時是從遠處開始繪製,因此遠處先繪製的多邊形可能被後繪製的多邊形覆蓋。

第二個座標系是三維網格組成的,座標(x,y,z),其中x和y是i和j的線性函數,通過座標轉換把原點變為中心點,然後通過xyrange進行縮放。高度z是f(x,y)的值。

第三個座標系是一個二維的畫布,起點(0,0)在左上方。畫布上任意點的座標(sx,sy),我們使用等角投影將三維點(x,y,z)投影到二維的畫布中。畫布上的點離右邊越遠,x和y值越大,z值越小。x和y的垂直縮放係數是30度角的sin值,水平縮放系統是30度角的cos值。z的縮放係數0.4是一個任意的值。

對於二維網格中的每一個網格單元,main函數會計算該單元在畫布上對應的多邊形ABCD的頂點,B對應頂點(i,j),A、C、D是B的鄰接點,然後輸出SVG的繪製指令。



文章所有權:Golang隱修會 連絡人:孫飛,CTO@188.com!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.