12|基本数据类型:Go原生支持的数值类型有哪些?
12|基本数据类型:Go原生支持的数值类型有哪些?
讲述:Tony Bai
时长21:41大小19.80M
被广泛使用的整型
整型的溢出问题
字面值与格式化输出
浮点型
浮点型的二进制表示
字面值与格式化输出
复数类型
延展:创建自定义的数值类型
小结
思考题
赞 34
提建议
精选留言(29)
- 罗杰2021-11-08float 其实相当复杂,开发中如果能避开就避开,例如金钱单位只有美元或者人民币我建议以分作为单位。
作者回复: 嗯,是这样的。
共 6 条评论53 - liaomars2021-11-09var f1 float32 = 16777216.0 var f2 float32 = 16777217.0 f1 == f2 // true f1 转换成二进制是:1266679808 f2 转换成二进制也是:1266679808 这个为什么是相等的,是因为转换成二进制的数据是相等的。展开
作者回复: 👍
30 - jc9090kkk2021-11-10type Myint int32 这种自定义类型在实际应用中有什么优势吗?
作者回复: 采用自定义类型时,我们考虑的角度不是优劣,而是需求。以type Myint int32为例,我们这么做,显然是因为int32不能满足我们的需求。哪些需求不能满足呢?第一个就是抽象,我们要建立更高级的抽象;第二个是我们不能为go原生类型int32增加我们想要的方法,只有通过自定义类型来实现。
18 - qinsi2021-11-1116777216.0 = 2^24 = (1+.0) * 2^24 因为float32的尾数只有23bit,能够表示的下一个数是 (1+2^(-23))*2^24 = 2^24+2 = 16777218.0 而16777217.0 = 2^24 + 1 = (1+2^(-24)) * 2^24,尾数得是2^(-24),需要24bit才能表示 直观上理解的话,实数是无限的,浮点数的二进制表示是有限的,所以必然有实数是无法用浮点数表示的。在实数轴上标出浮点数的话,相邻的浮点数之间就存在空洞。而且随着指数的增加,相邻浮点数之间的空洞也会越来越大。比如对于float32来说,2^24+1是第一个落在这样的空洞上的整数。而从2^25开始,下一个能表示的数就是(1+2^(-23))*2^25 = 2^25 + 4,中间会有3个整数无法表示。 同理,对于float64来说第一个无法表示的整数就是2^53+1(因为尾数只有52bit): ```go f1 := 9_007_199_254_740_992.0 f2 := 9_007_199_254_740_993.0 fmt.Println(f1 == f2) ``` (js程序员们表示这已经大于Number.MAX_SAFE_INTEGER了)展开共 2 条评论17
- 羊羊2021-11-080x1.Fp+0 // 1.9375 * 2^0 = 1.937500这个是如何计算得到的?0x1.F=1.9375是如何得到的?
作者回复: 0x1.Fp+0中的F是十六进制数,它的十进制值为15。F在小数点后一位,因此上面数字的小数部分0.F转换为10进制小数就是15 x 16^(-1)=0.9375
9 - Calvin2021-11-08很有意思,需要注意以下两者区别(两者语法很像,不注意空间混淆): 1)type MyInt int32 2)type MyInt = int32 1)比 2)少了一个“=”,两者含义却不同:1)是自定义了一个新类型 MyInt(底层类型是 int32),新类型与底层类型不能直接相互赋值和运算,如果需要,需要显式转换;2)是给 int32 类型定义了一个别名 MyInt(与 int32 完全等价),可以直接相互赋值和运算。展开共 3 条评论6
- 在下宝龙、2021-11-29type Myint int type MyMapp map[string]int func main(){ var x Myint var y int x=y//会报错 mp1:=make(MyMapp) mp2:=make(map[string]int) mp1=mp2 //不会报错 } 老师为甚么map就不会报错展开
作者回复: int与map[string]int虽然都是go原生类型,但它们却有不同。int在go中被归为defined type一类,而map[string]int则不是defined type。因此两个defined type: int与MyInt相互赋值必须显式转型。而map[string]int与MyMapp中,前者不是defined type,go语言有规定:这种情况下,可以直接赋值。具体参考这里:https://golang.google.cn/ref/spec#Assignability
5 - ryanxw2022-04-15工程开发中尽量不用浮点,像我们都要求用string来存价格
作者回复: 浮点用起来的确坑挺多。当然这也和其他实现原理有关。
3 - Howe2021-12-29老师,自定义类型和类型别名有什么样的应用场景?比如自定义一个类型,本质还是int32,那为啥不直接用int32,看起来感觉有点语法糖的意思,用处不大,特别是类型别名😢
作者回复: 原生的int32不能有方法,但自定义类型可以有方法哦。比如我定义一个名为Age的类型:type Age int32。Age可以作为“年龄”的抽象。我们可以为Age定义方法。至于类型别名,更多用于重构代码或基于已有包的二次封装。
3 - DullBird2021-11-1416777216=00000001 00000000 00000000 00000000 16777217=00000001 00000000 00000000 00000001 尾数只能放23位,但是需要24位才能表达167772173
- Kepler2022-03-06因为两个浮点数的差异在尾数M的第24位,超了
作者回复: ✅
2 - 松2022-01-28func main() { var f2 float32 = 16777216.0 var f3 float32 = 16777217.0 // 1001011100000000000000000000000 fmt.Printf("%b\n", math.Float32bits(f2)) // 1001011100000000000000000000000 fmt.Printf("%b\n", math.Float32bits(f3)) } 变量的二进制表示一样,所以相同了展开
作者回复: 👍
2 - Niverkk2022-01-21文中说Go 采用 2 的补码(Two’s Complement)作为整型的比特位编码方法 d1 := 0b10000001 fmt.Println(int8(d1)) //-127 fmt.Printf("%b\n", int8(-127)) // -1111111 但是格式化字面值仍是用原码吗?
作者回复: 似乎是。可能是go团队认为这这样的输出的结果更易于人类阅读:)。
1 - Vfeelit2022-01-09有很多语言没有无符号整数 无符号整数是否必要? 另外,没有无符号浮点数,是没有必要吗
作者回复: 1. 日常编码时,无符号整型使用频度相对于有符号的确小很多,并且无符号数溢出的问题很难检测。无符号唯一的优势在于其最大值表示范围比有符号整型大。 2. 从浮点类型的表示原理上讲似乎的确没有必要。
1 - 步比天下2022-01-01老师,您在介绍单精度浮点数的时候提到“偏移值的计算公式为 2^(e-1)-1,其中 e 为阶码部分的 bit 位数,这里为 8”,这个e是怎么计算得到的呢?我没有看懂啊
作者回复: e是阶码的bit位数,这个位数是规范定好的。见文中单精度与双精度的那张表。
1 - tequ1lAneio2021-11-09老师好,类型别名具体会在哪些场景用得到呢?
作者回复: 类型别名加入go的初衷就是为了重构,这也是其主要场景。在第17讲中还会有提及。
1 - JabariH2021-11-08package main import ( "fmt" "math" ) func main() { // 验证floate32类型精度不够导致的结果与常识不符合 var f1, f2 = float32(16777216.0), float32(16777217.0) var f11, f22 = float64(16777216.0), float64(16777217.0) if f1 == f2 { fmt.Println("float32 judge f1 == f2") } if f11 != f22 { fmt.Println("float64 judge f1 != f2") } f1_bits, f2_bits := math.Float32bits(f1), math.Float32bits(f2) fmt.Printf("float32 f1 convert to bits: %b\n", f1_bits) fmt.Printf("float32 f2 convert to bits: %b\n", f2_bits) f11_bits, f22_bits := math.Float64bits(f11), math.Float64bits(f22) fmt.Printf("float64 f1 convert to bits: %b\n", f11_bits) fmt.Printf("float64 f2 convert to bits: %b\n", f22_bits) } ➜ floatPrecision go run main.go float32 judge f1 == f2 float64 judge f1 != f2 float32 f1 convert to bits: 1001011100000000000000000000000 float32 f2 convert to bits: 1001011100000000000000000000000 float64 f1 convert to bits: 100000101110000000000000000000000000000000000000000000000000000 float64 f2 convert to bits: 100000101110000000000000000000000010000000000000000000000000000展开1
- 功夫熊猫2021-11-08float和double都存在精度差。我在c语言里做过0.999999和1比也相等共 2 条评论1
- 迈向架构师2023-01-29 来自广东有个小问题,我在正常代码中 判断 `int==int64`,能正常判断,但是使用goland打断点时的Alt+F8来运行这个`int==int64`却会报错,这是什么情况呀
作者回复: 有熟悉和经常使用goland的么,帮忙解答一下:)。
- 邹志鹏.Joey ⁷⁷...2023-01-18 来自广东平台相关整型感觉是设计缺陷, 真的会有人使用么? 很容易出错吧
作者回复: “缺陷”?言过了。平台相关类型在go中有广泛应用,只是在编写64bit和32bit平台都兼容的应用时,要注意一下而已。你翻一下go的runtime和标准库代码,能看到好多。