遵循 IEEE 754 标准(所有新式 CPU 都支持该标准),浮点数在计算机中的存储,分为三部分:
- 符号位,区分正数还是负数。
- 指数部分, float32 在 [0,255]区间内, Float64 在 [0,2047]区间内。
- 有效数字部分,在[0,1]区间内。
浮点数的值 = 符号位指数部分的值有效数字部分的值
Float32 数值的具体的计算过程如下:
package main
import (
"fmt"
"github.com/imroc/biu"
"math"
"strconv"
"strings"
)
func main() {
var i float32 = 99.99
exponentLen := 8 // 指数部分的长度
var middleware int64 = 127 // 中间数
// 获取完整的二进制存储值
str := biu.ToBinaryString(math.Float32bits(i))
fmt.Println("str: ", str)
// 只保留 0101 值
newStr := strings.ReplaceAll(str[1:len(str)-1], " ", "")
fmt.Println("newStr: ", newStr)
// 数值切分逻辑
sign := newStr[0:1]
exponent := newStr[1 : 1+exponentLen]
fraction := newStr[1+exponentLen:]
fmt.Println("sign: ", sign)
fmt.Println("exponent: ", exponent)
fmt.Println("fraction: ", fraction)
// 指数部分值计算逻辑
decimalExponent, _ := strconv.ParseInt(exponent, 2, 32)
fmt.Println("decimalExponent: ", decimalExponent)
exponentValue := 1 << (decimalExponent - middleware)
fmt.Println("exponentValue: ", exponentValue)
// 有效数字部分计算逻辑
decimalFraction, _ := strconv.ParseInt(fraction, 2, 32)
fmt.Println("decimalFraction: ", decimalFraction)
dividend := 1 << (len(newStr) - 1 - exponentLen)
fractionValue := float64(decimalFraction)/float64(dividend) + 1
fmt.Println("fractionValue: ", fractionValue)
fmt.Println(fractionValue * float64(exponentValue))
}
// 打印结果
/*
str: [01000010 11000111 11111010 11100001]
newStr: 01000010110001111111101011100001
sign: 0
exponent: 10000101
fraction: 10001111111101011100001
decimalExponent: 133
exponentValue: 64
decimalFraction: 4717281
fractionValue: 1.562343716621399
99.98999786376953
*/
对于 Float64 数值,只需要
- 将 exponentLen 的值改为 11;
- 将 middleware 的值改为 1023。
网友评论