go语言圣经练习答案——第二章程序结构

847 阅读2分钟

第一题

题意:向tempconv包添加类型、常量和函数用来处理Kelvin绝对温度的转换,Kelvin 绝对零度是−273.15°C,Kelvin绝对温度1K和摄氏度1°C的单位间隔是一样的。

package main

import (
	"fmt"
	"gopl/real_paragraph2/packageAndFile/tempconv"
)

func main() {
	var k tempconv.Kelvin = 1
	c := tempconv.KToC(k)
	fmt.Println(c)
	var c0 tempconv.Celsius = 0
	k0 := tempconv.CToK(c0)
	fmt.Println(k0)
}

运行结果:

第二题

题意: 写一个通用的单位转换程序,用类似cf程序的方式从命令行读取参数,如果缺省的话则是从标准输入读取参数,然后做类似Celsius和Fahrenheit的单位转换,长度单位可以对应英尺和米,重量单位可以对应磅和公斤等。

package main

import (
	"fmt"
	"os"
	"strconv"
)

//1英尺(ft)=0.3048米(m)
type Inch float64
type Meter float64

const tr float64 = 0.3048

func IToM (i Inch) Meter {
	return Meter(i * Inch(tr))
}

func MToI (m Meter) Inch {
	return Inch(m / Meter(tr))
}

func (i Inch) String() string {
	return fmt.Sprintf("%g inch",i)//注意转换格式需要是float类型的格式,这里用%g,不要用%v
}

func (m Meter) String() string {
	return fmt.Sprintf("%g meters",m)
}

func main() {
	for _,arg := range os.Args[1:]{
		t,err := strconv.ParseFloat(arg,64)
		if err != nil {
			fmt.Fprintf(os.Stderr,"transfer:%v\n",err)
			os.Exit(1)
		}
		i := Inch(t)
		m := Meter(t)
		fmt.Printf("%s = %s,%s = %s\n",i,IToM(i),m,MToI(m))
	}
}

运行结果示例:

第三题

题意:重写PopCount函数,用一个循环代替单一的表达式。

package popCount2_3

var pc [256]byte//byte只占一个字节

//pc被初始化为0-255无符号整数每一个数字所拥有的二进制1个数
func init() {
	for i := range pc {//只用了pc的索引值
		pc[i] = pc[i/2] + byte(i&1)
	}
}

//byte(x>>(n*8))截取低8位
func PopCount(x uint64) int {
	var temp int = 0
	for i := 0;i < 8;i++ {
		temp += int(pc[byte(x >> (i*8))])
	}
	return temp
}

第四题

题意:用移位算法重写PopCount函数,每次测试最右边的1bit,然后统计总数。

package popCount2_4

func PopCount(x uint64) int {
	var cnt int = 0
	for i := 0;i<64;i++ {
		cnt += ((x >> i) & 1)
	}
	return cnt
}

第五题

题意:表达式x&(x-1)用于将x的最低的一个非零的bit位清零。使用这个算法重写PopCount函数

package popCount2_5

func PopCount(x uint64) int {
	var cnt int = 0
	for x != 0 {
		x = x & (x - 1)
		cnt++
	}
	return cnt
}