day5 浮点数

master
dugulingping 2022-11-11 00:53:13 +08:00
parent 278314bd6f
commit 340bf90010
4 changed files with 198 additions and 0 deletions

View File

@ -17,6 +17,9 @@ func main() {
}
func handler(w http.ResponseWriter, r *http.Request) {
vars := r.URL.Query()
a := vars["a"][0]
fmt.Fprintf(w, a)
mu.Lock()
count++
mu.Unlock()

60
src/study/day5/float.go Normal file
View File

@ -0,0 +1,60 @@
package main
import (
"fmt"
"math"
"reflect"
)
// Go语言提供了两种精度的浮点数float32和float64。
// 它们的算术规范由IEEE754浮点数国际标准定义该浮点数规范被所有现代的CPU支持。
func main() {
// 浮点数类型的取值范围可以从很微小到很巨大。浮点数的范围极限值可以在math包找到。
fmt.Println(math.MaxFloat32)
fmt.Println(math.MaxFloat64)
// 一个float32类型的浮点数可以提供大约6个十进制数的精度
// 而float64则可以提供约15个十进制数的精度
// 通常应该优先使用float64类型
// 因为float32类型的累计计算误差很容易扩散并且float32能精确表示的正整数并不是很大
// 译注因为float32的有效bit位只有23个其它的bit位用于指数和符号
// 当整数大于23bit能表达的范围时float32的表示将出现误差
var f1 float32 = 16777216 // 1 << 24
fmt.Println(f1 == f1+1) // true
// 小数点前面或者后面的数都能被省略
f2, f3 := .2345, 67.
fmt.Println(reflect.TypeOf(f2), f2) // float64 0.2345
fmt.Println(reflect.TypeOf(f3), f3) // float64 67
// 很小或很大的数最好用科学计数法书写通过e或E来指定指数部分
const Avogadro = 6.02214129e23 // 阿伏伽德罗常数
const Planck = 6.62606957e-34 // 普朗克常数
// 用Printf格式化输出浮点数时使用%g或者%f可以用类似于%4.2f这种的格式输出
// 4表示距离前一个操作数有4个tab2表示保留两位小数输出
fmt.Printf("%g", 22.33)
fmt.Printf("\n %.4f %8.2f", 23.123456, 23.123456)
fmt.Printf("\n %.4f %8.2f\n", 23.133442, 23343.13456)
// IEEE754浮点数标准中定义的特殊值的创建和测试正无穷大和负无穷大
// 分别用于表示太大溢出的数字和除零的结果;
//还有NaN非数一般用于表示无效的除法操作结果0/0或Sqrt(-1).
var z float64
fmt.Println(z, -z, 1/z, -1/z, z/z) // "0 -0 +Inf -Inf NaN"
// 函数math.IsNaN用于测试一个数是否是非数NaNmath.NaN则返回非数对应的值。
// 虽然可以用math.NaN来表示一个非法的结果
// 但是测试一个结果是否是非数NaN则是充满风险的因为NaN和任何数都是不相等的
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
//}
}

59
src/study/day5/surface.go Normal file
View File

@ -0,0 +1,59 @@
// Surface computes an SVG rendering of a 3-D surface function.
package main
import (
"fmt"
"math"
)
const (
width, height = 600, 320 // 画布大小
cells = 100 // 单元格大小
xyrange = 30.0 // 坐标轴范围 (-xyrange..+xyrange)
xyscale = width / 2 / xyrange // x或y轴上每个单位长度的像素
zscale = height * 0.4 // z轴上每个单位长度的像素
angle = math.Pi / 6 // x、y轴的角度(=30°)
)
var sin30, cos30 = math.Sin(angle), math.Cos(angle) // sin(30°), cos(30°)
var ConcerError error
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 style='stroke: red;' 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) {
// 求出网格单元(i,j)的顶点坐标(x,y)
x := xyrange * (float64(i)/cells - 0.5)
y := xyrange * (float64(j)/cells - 0.5)
// 计算曲面高度 z.
z := f(x, y)
// 将(x, y, z)等角投射到二维SVG绘图平面上,坐标是(sx, sy)
sx := width/2 + (x-y)*cos30*xyscale
sy := height/2 + (x+y)*sin30*xyscale - z*zscale
if math.IsNaN(sx) || math.IsNaN(sy) {
ConcerError = fmt.Errorf("corner() 产生非数值")
}
return sx, sy
}
func f(x, y float64) float64 {
r := math.Hypot(x, y) // 到 (0,0) 的距离
return math.Sin(r) / r
}

View File

@ -0,0 +1,76 @@
package main
import (
"fmt"
"log"
"math"
"net/http"
)
const (
width, height = 600, 320 // 画布大小
cells = 100 // 单元格大小
xyrange = 30.0 // 坐标轴范围 (-xyrange..+xyrange)
xyscale = width / 2 / xyrange // x或y轴上每个单位长度的像素
zscale = height * 0.4 // z轴上每个单位长度的像素
angle = math.Pi / 6 // x、y轴的角度(=30°)
)
var sin30, cos30 = math.Sin(angle), math.Cos(angle) // sin(30°), cos(30°)
var ConcerError error
func main() {
http.HandleFunc("/", surface)
log.Fatal(http.ListenAndServe("localhost:8080", nil))
}
func surface(w http.ResponseWriter, r *http.Request) {
vars := r.URL.Query()
stroke := vars.Get("stroke")
if stroke == "" {
stroke = "red"
}
fill := vars.Get("fill")
if fill == "" {
fill = "blue"
}
w.Header().Set("Content-Type", "image/svg+xml")
fmt.Fprintf(w, `<svg xmlns='http://www.w3.org/2000/svg'
style='stroke: %s; fill: %s; stroke-width: 0.7' width='%d' height='%d'>`,
stroke, fill, width, height)
fmt.Fprint(w, "\n")
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.Fprintf(w, "<polygon style='stroke: %s;' points='%g,%g %g,%g %g,%g %g,%g'/>\n",
stroke, ax, ay, bx, by, cx, cy, dx, dy)
}
}
fmt.Fprint(w, "</svg>")
}
func corner(i, j int) (float64, float64) {
// 求出网格单元(i,j)的顶点坐标(x,y)
x := xyrange * (float64(i)/cells - 0.5)
y := xyrange * (float64(j)/cells - 0.5)
// 计算曲面高度 z.
z := f(x, y)
// 将(x, y, z)等角投射到二维SVG绘图平面上,坐标是(sx, sy)
sx := width/2 + (x-y)*cos30*xyscale
sy := height/2 + (x+y)*sin30*xyscale - z*zscale
if math.IsNaN(sx) || math.IsNaN(sy) {
ConcerError = fmt.Errorf("corner() 产生非数值")
}
return sx, sy
}
func f(x, y float64) float64 {
r := math.Hypot(x, y) // 到 (0,0) 的距离
return math.Sin(r) / r
}