// 第 1 周 – 实践课练习的参考答案（Go 版）
// 运行：go run ./w01/exercises
package main

import (
	"fmt"
	"math"
	"strconv"
)

// E1. 存放整数 n >= 0 需要多少位？
func bitsNeeded(n int64) int {
	bits := 1
	for n > 1 {
		n = n / 2
		bits++
	}
	return bits
}

// E2. 用反复除法求二进制形式。
func toBinary(n int) string {
	if n == 0 {
		return "0"
	}
	result := ""
	for n > 0 {
		result = strconv.Itoa(n%2) + result
		n = n / 2
	}
	return result
}

// E3. 利用字符编码把小写字母转换成大写字母。
func toUpper(c rune) rune {
	if c >= 'a' && c <= 'z' {
		return c - ('a' - 'A')
	}
	return c
}

// E4. 带容差判断两个实数是否相等。
func almostEqual(x, y float64) bool {
	return math.Abs(x-y) < 1e-9
}

// E5. 真值表。Go 没有逻辑异或运算符：a != b 的结果相同。
func truthTable() {
	fmt.Println("  a      b      a&&b   a||b   !a     a!=b")
	for _, a := range []bool{false, true} {
		for _, b := range []bool{false, true} {
			fmt.Printf("  %-6v %-6v %-6v %-6v %-6v %-6v\n", a, b, a && b, a || b, !a, a != b)
		}
	}
}

// E6. 在相加之前检测溢出（int32）。
func addWouldOverflow(x, y int32) bool {
	if y > 0 {
		return x > math.MaxInt32-y
	}
	if y < 0 {
		return x < math.MinInt32-y
	}
	return false
}

func main() {
	x := 0.1
	fmt.Println("E1. bitsNeeded(255) =", bitsNeeded(255), ", bitsNeeded(256) =", bitsNeeded(256))
	fmt.Println("E2. toBinary(50) =", toBinary(50), " (check:", strconv.FormatInt(50, 2)+")")
	fmt.Printf("E3. toUpper('g') = %c, toUpper('7') = %c\n", toUpper('g'), toUpper('7'))
	fmt.Println("E4. almostEqual(0.1+0.2, 0.3) =", almostEqual(x+0.2, 0.3))
	fmt.Println("E5.")
	truthTable()
	fmt.Println("E6. MaxInt32 + 1 overflows?", addWouldOverflow(math.MaxInt32, 1))
	fmt.Println("    1000 + 2000 overflows?   ", addWouldOverflow(1000, 2000))
}
