typora/note/Go/数据类型.md
2024-12-12 10:48:55 +08:00

5.4 KiB
Raw Blame History

整型

  • 平台无关整型
  • 平台相关整型
  • 区别在于整数类型在不同 CPU 架构或操作系统下面,它们的长度是否是一致

平台无关整型

  • 任何CPU架构下长度都是一致的
  • 有符号整数 int8-int64
  • 无符号整数 uint8-unint64
  • 本质差别在于最高二进制位bit 位)是否被解释为符号位

平台相关整型

  • int
  • uint
  • uintptr
  • 可以调用unsafe.Sizeof(变量) 方法来获取对应平台占用的大小

整型溢出

  • 整型运算结果超出表示的范围
  • 溢出的结果依然在整型表示范围
  • 结果与预期结果不符

var s int8 = 127
s += 1 // 预期128实际结果-128

var u uint8 = 1
u -= 2 // 预期-1实际结果255

整型字面值与格式化输出

  • 二进制
  • 八进制
  • 十进制
  • 十六进制
d1 := 0b10000001 // 二进制,以"0b"为前缀在go1.13之后的版本才生效
d2 := 0B10000001 // 二进制,以"0B"为前缀在go1.13之后的版本才生效

b := 0700      // 八进制,以"0"为前缀
e1 := 0o700      // 八进制,以"0o"为前缀
e2 := 0O700      // 八进制,以"0O"为前缀

a := 53        // 十进制

c1 := 0xaabbcc // 十六进制,以"0x"为前缀
c2 := 0Xddeeff // 十六进制,以"0X"为前缀

支持在字面值中增加数字分隔符"-"

  • 在go1.13之后的版本才生效

a := 5_3_7   // 十进制: 537
b := 0b_1000_0111  // 二进制位表示为10000111 
c1 := 0_700  // 八进制: 0700
c2 := 0o_700 // 八进制: 0700
d1 := 0x_5c_6d // 十六进制0x5c6d

浮点数

  • float32 32位单精度浮点数
  • float64 64位双精度浮点数
  • 默认值0.0
  • Go提供的浮点数都是平台无关的

浮点数二进制表示

  • IEEE 754算术标准
  • 单精度 32位
  • 双精度 64位
  • 扩展单精度 43位以上
  • 扩展双精度 79位以上
  • 二进制表示方式

浮点数阶码和尾数

十进制小数转换成二进制计算方式

  • 乘2取整的竖式计算
  • 小数部分每次乘2结果大于1记1结果小于1记0
  • 剩下的小数部分再乘2记录方式同上
  • 直到结果等于小数部分为0

十进制形式的浮点值 139.8125转换为IEEE754单精度二进制

二进制转换
  • 整数部分转换为二进制 10001011b
  • 小数部分转换为二进制 1101b
  • 原来的139.8125变为10001011.1101
移动小数点直到整数部分仅有1个1
  • 10001011.1101b => 1.00010111101b
  • 小数点移动7位
  • 尾数为00010111101b
计算阶码
  • 阶码 = 指数 + 偏移值指数就是小数点移动的位数偏移值为2^(e-1)-1e就是阶码部分的bit位数32位精度e为8,64精度e为11
  • 阶码 = 7 + 127为134d10000110b
符号位阶码和尾数填充尾数位不够的话补0
  • 符号位 0
  • 阶码 10000110
  • 尾数 00010111101(000000000000)补充12个0
  • 二进制139.8125的表示方式就是0b_0_10000110_00010111101_000000000000

func main() {
    var f float32 = 139.8125
    bits := math.Float32bits(f)
    fmt.Printf("%b\n", bits)// 高危补0表示符号位
    // 1000011000010111101000000000000
}

字面值与格式化输出

字面值
  • 十进制表示浮点值的形式
3.1415
.15  // 整数部分如果为0整数部分可以省略不写
81.80
82. // 小数部分如果为0小数点后的0可以省略不写
  • 科学计数法
v
6674.28e-2 // 6674.28 * 10^(-2) = 66.742800
.12345E+5  // 0.12345 * 10^5 = 12345.000000
  • 16进制科学计数法整数和小数部分用的都是16进制但是指数部分依然是10进制
0x2.p10  // 2.0 * 2^10 = 2048.000000
0x1.Fp+0 // 1.9375 * 2^0 = 1.937500
格式化
  • %f格式化
var f float64 = 123.45678
fmt.Printf("%f\n", f) // 123.456780
  • 输出科学计数法形式
var f float64 = 123.45678
fmt.Printf("%e\n", f) // 1.234568e+02 十进制科学计数法
fmt.Printf("%x\n", f) // 0x1.edd3be22e5de1p+06 16进制科学计数法

复数

  • complex64实部与虚部都是float32
  • complex128实部与虚部都是float64
  • 如果一个复数没有显示赋予类型则默认类型为complex128

字面值与初始化

  • 通过字面值直接初始化

var c = 5 + 6i
var d = 0o123 + .12345E+5i // 83+12345i
  • complex 函数,方便创建一个 complex128 类型值

var c = complex(5, 6) // 5 + 6i
var d = complex(0o123, .12345E+5) // 83+12345i
  • 通过预定义函数 realimag来获取一个复数的实部和虚部

var c = complex(5, 6) // 5 + 6i
r := real(c) // 5.000000
i := imag(c) // 6.000000

创建自定义的数值类型

  • type MyInt int32
  • MyInt底层仍然是int32数值性质也与int32相同
  • 但是Go的类型安全规则限定MyInt和int32仍是完全不同的两种类型无法进行相互复制和计算
  • 赋值和计算需显示类型转换

通过类型别名来定义数值类型

  • type MyInt = int32
  • 通过类型别名语法定义的新类型与原类型别无二致,可以完全相互替代