浮点型底层
1. 浮点型
浮点数,计算机中小数的表示方式,如:3.14
Go语言中提供了两种浮点型:
- float32,用32位(4个字节)来存储浮点型。
- float64,用64位(8个字节)来存储浮点型。
package main
import "fmt"
func main() {
var v1 float32
v1 = 3.14
v2 := 99.9
v3 := float64(v1) + v2
fmt.Println(v1, v2, v3)
}
1.1. 非精确
float类型,计算机中小数的非精确的表示方式,如:3.14
package main
import "fmt"
func main() {
var v1 float32
v1 = 3.14
v2 := 99.9
v3 := float64(v1) + v2
fmt.Println(v1, v2, v3)
v4 := 0.1
v5 := 0.2
result := v4 + v5
fmt.Println(result)
v6 := 0.3
v7 := 0.2
data := v6 + v7
fmt.Println(data)
}
3.14 99.9 103.04000010490418
0.30000000000000004
0.5
1.2. float底层存储原理
var price float32 = 0.29
第一步:浮点型转换为二进制
- 整数部分,直接转换为二进制(10进制转换为2进制),即:
100111
小数部分,让小数部分乘以2,结果小于1则将结果继续乘以2,结果大于1则讲结果-1继续乘以2,结果等于1则结束。
0.29 * 2 = 0.58 // 小于1,则继续乘 0.58 * 2 = 1.16 // 大于1,则减1继续乘 0.16 * 2 = 0.32 // 小于1,则继续乘 0.32 * 2 = 0.64 // 小于1,则继续乘 0.64 * 2 = 1.28 // 大于1,则减1继续乘 0.28 * 2 = 0.56 // 小于1,则继续乘 0.56 * 2 = 1.12 // 大于1,则减1继续乘 0.12 * 2 = 0.24 // 小于1,则继续乘 0.24 * 2 = 0.48 // 小于1,则继续乘 0.48 * 2 = 0.96 // 小于1,则继续乘 0.96 * 2 = 1.92 // 大于1,则减1继续乘 0.92 * 2 = 1.84 // 大于1,则减1继续乘 0.84 * 2 = 1.68 // 大于1,则减1继续乘 0.68 * 2 = 1.36 // 大于1,则减1继续乘 0.36 * 2 = 0.72 // 小于1,则继续乘 0.72 * 2 = 1.44 // 大于1,则减1继续乘 0.44 * 2 = 0.88 // 小于1,则继续乘 0.88 * 2 = 1.76 // 大于1,则减1继续乘 0.76 * 2 = 1.52 // 大于1,则减1继续乘 0.52 * 2 = 1.04 // 大于1,则减1继续乘 0.04 * 2 = 0.08 // 小于1,则继续乘 0.08 * 2 = 0.16 // 小于1,则继续乘 0.16 * 2 = 0.32 // 小于1,则继续乘(与第三行相同,这样会一直循环执行下去) ... 将相乘之后等结果的整数部分拼接起来,所以 0.29的 二进制表示:010010100011110101110000101000111...
所以,最终39.29的二进制表示为:100111.010010100011110101110000101000111...
第二步:科学计数法表示
100111.010010100011110101110000101000111...
$$ 1.00111010010100011110101110000101000111... * 2^5 $$
第三步:存储
以float32为例来进行存储,用32位来存储浮点型
- sign,用1位来表示浮点数正负,0表示正数;1表示负数。
- exponent,用8位来表示共有256种(0~255),含正负值(-127 ~ 128)。例如:5想要存储到exponent位的话,需要让 5 + 127 = 132,再讲132转换二进制,存储到exponent。(132的二进制是:01000010)
- fraction,存储小数点后的所有数据。
float64和float32类似,只是用于表示各部分的位数不同而已,其中:sign=1位
、exponent=11位
、fraction=52位
,也就意味着可以表示的范围更大了。