<The Go Programming Language>第二章习题答案

    科技2025-06-05  26

    2.1 Names Key: break; default; func; interface; select; case; defer; go; map; struct; chan; else; goto; package; switch; const; fallthrough; if; range; type; continue; for; import; return; var; Constans: ture; false; iota; nil; Functions: make; len; cap; new; append; copy; close; delete; complex; real; imag; panic; recover; var; const; type; func; boiling package main import "fmt" const boilingF = 212.0 func main(){ var f = boilingF var c = (f-32)*5/9 fmt.Printf("boiling point = %g°F or %g℃\n", f, c) } Output: boiling point = 212°F or 100℃

    ftoc

    package main import "fmt" func main(){ const freezingF, boilingF = 32.0, 212.0 fmt.Printf("%g°F = %g℃\n", freezingF, fToC(freezingF)) fmt.Printf("%g°F = %g℃\n", boilingF, fToc(boilingF)) } func fToc(f float64) float64{ return (f-32)*5 / 9 } echo4 package main import( "flag" "fmt" "strings" ) var n = flag.Bool("n", false, "omit trailing newline") var sep = flag.String("s", " ", "separator") func main(){ flag.Parse() fmt.Print(strings.Join(flag.Args(), *sep)) if !*n{ fmt.Println() } } 2.1 在tempconv中添加类型,常量和函数,以开尔文标度处理温度,其中零开尔文为-273.15,相差1K的大小等于1。 package tempconv import "fmt" func CToF(c Celsius) Fahrenheit { return Fahrenheit(c*9/5 + 32) } func FToC(f Fahrenheit) Celsius { return Celsius((f - 32) * 5 / 9)} func CTok(c Celsius) Kelvins { return Kelvins(c - AbsoluteZeroC) } func KtoC(k Kelvins) Celsius { return Celsius(k + Kelvins(AbsoluteZeroC)) } package tempconv import "fmt" type Celsius float64 type Fahrenheit float64 type Kelvins float64 const ( AbsoluteZeroC Celsius = -273.15 FreezingC Celsius = 0 BoilingC Celsius = 100 ) func (c Celsius) String() string { return fmt.Sprintf("%g°C", c) } func (f Fahrenheit) String() string { return fmt.Sprintf("%g°F", f) } func (k Kelvins) String() string { return fmt.Sprintf("%g k", k) } 2.2 写一个类似于cf的通用的单位转换程序,从命令行参数或者标准输入(如果没有参数)获取数字,然后将每一个数字转换为摄氏温度和华氏温度表示的温度,以英寸和米表示的长度单位,比磅和千克表示的重量,等等。 package tempconv func CToF(c Celsius) Fahrenheit { return Fahrenheit(c*9/5 + 32) } func FToC(f Fahrenheit) Celsius { return Celsius((f - 32) * 5 / 9)} func CTok(c Celsius) Kelvins { return Kelvins(c - AbsoluteZeroC) } func KtoC(k Kelvins) Celsius { return Celsius(k + Kelvins(AbsoluteZeroC)) } func IToM(i Inch) Meter { return Meter(i * 0.0254) } func MToI(m Meter) Inch { return Inch(m / 0.0254) } func ITok(i Ib) Kilogram { return Kilogram(i * 0.4535) } func KToI(k Kilogram) Ib { return Ib(k / 0.4535) } package tempconv import "fmt" type Celsius float64 type Fahrenheit float64 type Kelvins float64 type Inch float64 type Meter float64 type Ib float64 type Kilogram float64 const ( AbsoluteZeroC Celsius = -273.15 FreezingC Celsius = 0 BoilingC Celsius = 100 ) func (c Celsius) String() string { return fmt.Sprintf("%g°C", c) } func (f Fahrenheit) String() string { return fmt.Sprintf("%g°F", f) } func (k Kelvins) String() string { return fmt.Sprintf("%g k", k) } func (i Inch) String() string { return fmt.Sprintf("%g in", i) } func (m Meter) String() string { return fmt.Sprintf("%g m", m) } func (i Ib) String() string { return fmt.Sprintf("%g ib", i) } func (k Kilogram) String() string { return fmt.Sprintf("%g kg", k) }

    -2.3 使用循环重写PopCount来代替单个表达式。对比两个版本的效率。

    package main import( "fmt" "time" ) var pc [256]byte func init(){ for i, _ := range pc { pc[i] = pc[i/2] + byte(i&1) } } func TimeConsuming(tag string) func(){ now := time.Now().UnixNano() return func(){ after := time.Now().UnixNano() fmt.Printf("%q time cost %d ns\n", tag, after-now) } } func PopCount1(x uint64) int { defer TimeConsuming("PopCount1")() return int(pc[byte(x>>(0*8))] + pc[byte(x>>(1*8))] + pc[byte(x>>(2*8))] + pc[byte(x>>(3*8))] + pc[byte(x>>(4*8))] + pc[byte(x>>(5*8))] + pc[byte(x>>(6*8))] + pc[byte(x>>(7*8))]) } func PopCount2(x uint64) int { defer TimeConsuming("Popcount2")() var n int for i := 0; i < 8; i++{ n += int(pc[byte(x>>(i*8))]) } return n } package main import ( "fmt" ) func main(){ fmt.Println(PopCount1(257)) fmt.Println(PopCount2(257)) } 2.4 编写一个PopCount版本,该版本通过将其参数移至64位位置来计数位,每次都测试最右边的位。将其性能雨表查找版本进行比较。 package main import( "fmt" "time" ) var pc [256]byte func init(){ for i, _ := range pc { pc[i] = pc[i/2] + byte(i&1) } } func TimeConsuming(tag string) func(){ now := time.Now().UnixNano() return func(){ after := time.Now().UnixNano() fmt.Printf("%q time cost %d ns\n", tag, after-now) } } func PopCount1(x uint64) int { defer TimeConsuming("PopCount1")() return int(pc[byte(x>>(0*8))] + pc[byte(x>>(1*8))] + pc[byte(x>>(2*8))] + pc[byte(x>>(3*8))] + pc[byte(x>>(4*8))] + pc[byte(x>>(5*8))] + pc[byte(x>>(6*8))] + pc[byte(x>>(7*8))]) } func PopCount2(x uint64) int { defer TimeConsuming("Popcount2")() var n int for i := 0; i < 8; i++{ n += int(pc[byte(x>>(i*8))]) } return n } func PopCount3(x uint64) int { defer TimeConsuming("PopCount3")() var x_ = x var n int for i := 0; i < 8; i++{ x_ = x_>>(i*8) if(x_&1) == 1{ n++ } } return n } 2.5 表达式x&(x-1)清除x的最右边的非零位。编写一个使用此事实对位数进行计数的PopCount版本,并评估其性能。 package main import( "fmt" "time" ) var pc [256]byte func init(){ for i, _ := range pc { pc[i] = pc[i/2] + byte(i&1) } } func TimeConsuming(tag string) func(){ now := time.Now().UnixNano() return func(){ after := time.Now().UnixNano() fmt.Printf("%q time cost %d ns\n", tag, after-now) } } func PopCount1(x uint64) int { defer TimeConsuming("PopCount1")() return int(pc[byte(x>>(0*8))] + pc[byte(x>>(1*8))] + pc[byte(x>>(2*8))] + pc[byte(x>>(3*8))] + pc[byte(x>>(4*8))] + pc[byte(x>>(5*8))] + pc[byte(x>>(6*8))] + pc[byte(x>>(7*8))]) } func PopCount2(x uint64) int { defer TimeConsuming("Popcount2")() var n int for i := 0; i < 8; i++{ n += int(pc[byte(x>>(i*8))]) } return n } func PopCount3(x uint64) int { defer TimeConsuming("PopCount3")() var n int for i := 0; i < 8; i++{ x = x>>(i*8) if(x&1) == 1{ n++ } } return n } func PopCount4(x uint64) int { defer TimeConsuming("Popcount4")() var n int for i := 0; i < 8; i++{ x = x>>(i*8) if(x&(x-1)) == (x-1){ n++ } } return n }
    Processed: 0.012, SQL: 8