GO语言圣经 第二章习题

练习2.1

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

conv.go

package tempconv

// CToF converts a Celsius temperature to Fahrenheit.
func CToF(c Celsius) Fahrenheit { return Fahrenheit(c*9/5 + 32) }

// FToC converts a Fahrenheit temperature to Celsius.
func FToC(f Fahrenheit) Celsius { return Celsius((f - 32) * 5 / 9) }

func KToC(k Kelvin) Celsius { return Celsius(k + 273.15) }

func CToT(c Celsius) Kelvin { return Kelvin(c + 273.15) }

tempconv.go

package tempconv

import "fmt"

type Celsius float64
type Fahrenheit float64
type Kelvin 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 Kelvin) String() string     { return fmt.Sprintf("%g°K", k) }

练习2.2

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

conv.go:

package lenthconv

func MToF(m Meter) Feet { return Feet(m / 0.3084) }

func FToM(f Feet) Meter { return Meter(f * 0.3084) }

lenthconv:

package lenthconv

import "fmt"

type Meter float64
type Feet float64

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

test:

package main

import (
	"bufio"
	"fmt"
	"os"
	"strconv"

	"gopl.io/ch2/lenthconv"
)

func main() {
	if len(os.Args) == 1 {
		input := bufio.NewScanner(os.Stdin)
		for input.Scan() {
			t, err := strconv.ParseFloat(input.Text(), 64)
			if err != nil {
				fmt.Fprintf(os.Stderr, "cf: %v\n", err)
				os.Exit(1)
			}
			f := lenthconv.Feet(t)
			m := lenthconv.Meter(t)
			fmt.Printf("%s = %s, %s = %s\n",
				f, lenthconv.FToM(f), m, lenthconv.MToF(m))

		}
	}
	for _, arg := range os.Args[1:] {
		t, err := strconv.ParseFloat(arg, 64)
		if err != nil {
			fmt.Fprintf(os.Stderr, "cf: %v\n", err)
			os.Exit(1)
		}
		f := lenthconv.Feet(t)
		m := lenthconv.Meter(t)
		fmt.Printf("%s = %s, %s = %s\n",
			f, lenthconv.FToM(f), m, lenthconv.MToF(m))
	}
}

练习2.3

重写PopCount函数,用一个循环代替单一的表达式。比较两个版本的性能。

func PopCount(x uint64) int {
	res := 0
	for i := 0; i < 8; i++ {
		res += int(pc[byte(x>>(i*8))])
	}
	return res
}

练习2.4

用移位算法重写PopCount函数,每次测试最右边的1bit,然后统计总数。比较和查表算法的性能差异。

func PopCount(x uint64) int {
	res := 0
	for x != 0 {
		res += x & 1
		x >>= 1
	}
	return res
}

练习2.5

表达式x&(x-1)用于将x的最低的一个非零的bit位清零。使用这个算法重写PopCount函数,然后比较性能。

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

你可能感兴趣的:(GO语言圣经习题,golang,开发语言)