【go语言圣经】习题答案 第二章

祁晟
2023-12-01

2.1 添加Kelvin绝对温度的转换

// 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) }

// 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) }

// CToK converts a Celsius temperature to Kelvin.
func CToK(c Celsius) Kelvin { return Kelvin(c + AbsoluteZeroC) }

// KToC  converts a Kelvin temperature to Celsius.
func KToC(k Kelvin) Celsius { return Celsius(k) - AbsoluteZeroC }

// FToK converts a Celsius temperature to Kelvin.
func FToK(f Fahrenheit) Kelvin { return Kelvin(FToC(f) + AbsoluteZeroC) }

// KToF converts a Kelvin temperature to Fahrenheit.
func KToF(k Kelvin) Fahrenheit { return CToF(Celsius(k) - AbsoluteZeroC) }
// main.go
package main

import (
	"ch2/tempconv"
	"fmt"
	"os"
	"strconv"
)

// 添加Kelvin绝对温度的转换
func test_2_1() {
	for _, arg := range os.Args[1:] {
		temp, err := strconv.ParseFloat(arg, 64)
		if err != nil {
			fmt.Println("arguments have problems, try again.")
		}
		c := tempconv.Celsius(temp)
		f := tempconv.Fahrenheit(temp)
		k := tempconv.Kelvin(temp)
		fmt.Printf("%s=%s=%s\n", c, tempconv.CToF(c), tempconv.CToK(c))
		fmt.Printf("%s=%s=%s\n", tempconv.FToC(f), f, tempconv.FToK(f))
		fmt.Printf("%s=%s=%s\n\n", tempconv.KToC(k), tempconv.KToF(k), k)
	}
}

func main() {
	test_2_1()
}

2.2 长度转换

// lenconv.go
package lenconv

import "fmt"

type Meter float64
type Foot float64

// Meter,Foot的输出方式
func (m Meter) String() string { return fmt.Sprintf("%fm", m) }
func (f Foot) String() string  { return fmt.Sprintf("%fft", f) }

// Meter,Foot的转换方式
func MToF(m Meter) Foot { return Foot(m * 3.28084) }
func FToM(f Foot) Meter { return Meter(f * 0.3048) }
// main.go
func test_2_2() {
	if len(os.Args) == 1 {
		var l float64
		fmt.Println("please input a number float64")
		_, err := fmt.Scan(&l)
		if err != nil {
			fmt.Printf("arguments errors,error:%v\n", err)
			return
		}
		m := lenconv.Meter(l)
		f := lenconv.Foot(l)
		fmt.Printf("%s=%s\n", m, lenconv.MToF(m))
		fmt.Printf("%s=%s\n\n", f, lenconv.FToM(f))
		return
	}
	for _, arg := range os.Args[1:] {
		l, err := strconv.ParseFloat(arg, 64)
		if err != nil {
			fmt.Printf("arguments errors,error:%v\n", err)
		}
		m := lenconv.Meter(l)
		f := lenconv.Foot(l)
		fmt.Printf("%s=%s\n", m, lenconv.MToF(m))
		fmt.Printf("%s=%s\n\n", f, lenconv.FToM(f))
	}
}

2.3 2.4 重写PopCount函数,用一个循环代替单一的表达式

// 重写PopCount函数,用一个循环代替单一的表达式
var pc [256]byte

func init() {
	for i := range pc {
		pc[i] = pc[i/2] + byte(i&1)
	}
}

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

func test_2_3() {
	var num uint64
	fmt.Printf("please enter a number:")
	_, err := fmt.Scan(&num)
	if err != nil {
		fmt.Println("input error,err:", err)
		return
	}
	start := time.Now()
	fmt.Printf("%d has %d set bits\n", num, PopCount(num))
	fmt.Printf("%fs has passed\n", time.Since(start).Seconds())
}

2.5 用移位算法重写PopCount函数

// 用移位算法重写PopCount函数
func PopCount(num uint64) int {
	ans := 0
	for num != 0 {
		num = num & (num - 1)
		ans++
	}
	return ans
}

func test_2_5() {
	fmt.Printf("Please enter a number:")
	var num uint64
	_, err := fmt.Scan(&num)
	if err != nil {
		fmt.Println("input error:", err)
		return
	}
	start := time.Now()
	fmt.Printf("%d has %d set bits\n", num, PopCount(num))
	fmt.Printf("%d Nanoseconds has passed\n", time.Since(start).Nanoseconds())
}
 类似资料: