• 2.如何选择go语言基础类型——Leetcode习题9


    本篇前瞻

    欢迎来go语言的基础篇,这里会帮你梳理一下go语言的基本类型,注意本篇有参考go圣经,如果你有完整学习的需求可以看一下。另外,go语言的基本类型比较简单,介绍过程就比较粗暴,不过我们需要先从一个例题开始。

    Leetcode习题9

    先让我们看下这个来自leetcode的例子,这个是一个比较好的例子,里面有一些关于整形的的知识

    题目描述

    9. 回文数

    给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false

    回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。

    原题解析

    注意原题中已经提供了一个go语言的函数

    func isPalindrome(x int) bool {
    }
    

    为了方便我们编写代码,我们只需要知道这个函数的输入是x,输出是代表是否是回文数(是:true,否:false),return能返回输出。

    解题方法:

    1. 负数必然不是回文数。

    2. 对于非负整数,我们循环x除10,通过x%10获得最低位,并且把最低位当作最高位加入到px中,得到了x的反转过来的数px

    3. 判断pxx是否相等就可以了。

    代码编写

    使用int32来计算px, 将如下代码提交,不行,答案错误,这是因为如果x=2147483647,那么px=7463847412,超出int32的范围了

    func isPalindrome(x int) bool {
    	if x < 0 {
    		return false
    	}
    
    	x32 := int32(x)
    	px32 := int32(x)
    	for x32 != 0 {
    		px32 = px32*10 + x32%10
    		x32 /= 10
    	}
    	return px32 == int32(x)
    }
    

    那么换成int64代码如下,提交通过了,我们花费了28ms,仅仅击败12%的人,时间上有问题吗?

    func isPalindrome(x int) bool {
    	if (x < 0) {
    		return false
    	}
    	x64 := int64(x)
    	px64 := int64(0)
    	for x64 != 0 {
    		px64 = px64*10 + x64%10
    		x64 /= 10
    	}
    	return px64 == int64(x)
    }
    

    现在尝试去掉int64的强制转化,居然通过了,只花费4ms,击败了97%的人,这不可思议!

    func isPalindrome(x int) bool {
    	if (x < 0) { 
    		return false
    	}
    	x64 := x   //整形 
    	px64 := 0
    	for x64 != 0 { 
    		px64 = px64*10 + x64%10 
    		x64 /= 10
    	}
    	return px64 == x //布尔型
    }
    

    有符号整形

    这种整形就是可以表示负整数,0和正整数

    数据类型 占用空间(bit) 长度(字节) 取值范围
    int8 8 1 -2^7 ~ 2^7-1(-128~127)
    int16 16 2 -2^15 ~ 2^15-1(-32768 ~ 32767)
    int32 32 4 -2^32 ~ 2^32-1(-2147483648 ~ 2147483647)
    int64 64 8 -2^64 ~ 2^64-1(-9223372036854775808 ~ 9223372036854775807)
    int 32或64 4或8 同int32或int64

    注意:int的占用空间取决于你的操作系统是32位或64位

    那么利用这三次提交的结果,并结合有符号整形的知识,我们可以得出:

    1. 变量强制类型转化会耗时
    2. 编程中的变量的取值范围很重要
    3. Leetcode的判题系统是64位的

    基本数据类型

    从上面的例题中我们能发现数据类型的选择在编程过程中有着决定性的作用,虽然这很基础,但是决定了你的编程结果是否正确,选择合适的类型会使你编写的程序运行速度更快,占用内存更小。

    注意:由于复数类型不常用的关系,本章节不会介绍该类型。

    整形

    这个不是韩国的“绝学”——整形术,整形在编程中可以表示一定范围内的整数

    注意:int或uint的占用空间取决于你的操作系统是32位或64位

    对于整形我们要关注的是数据类型的长度,数据范围

    代码如下:

    package main
    
    import (
    	"fmt"
    	"math"
    	"unsafe"
    )
    
    func main() {
    	fmt.Printf("int8   length: %v range: %v ~ %v\n", unsafe.Sizeof(int8(1)), math.MinInt8, math.MaxInt8)
    	fmt.Printf("int16  length: %v range: %v ~ %v\n", unsafe.Sizeof(int16(1)), math.MinInt16, math.MaxInt16)
    	fmt.Printf("int32  length: %v range: %v ~ %v\n", unsafe.Sizeof(int32(1)), math.MinInt32, math.MaxInt32)
    	fmt.Printf("int64  length: %v range: %v ~ %v\n", unsafe.Sizeof(int64(1)), math.MinInt64, math.MaxInt64)
    	fmt.Printf("int    length: %v\n", unsafe.Sizeof(int(1)))
    
    	fmt.Printf("uint8  length: %v range: 0 ~ %v\n", unsafe.Sizeof(uint8(1)), math.MaxUint8)
    	fmt.Printf("uint16 length: %v range: 0 ~ %v\n", unsafe.Sizeof(uint16(1)), math.MaxUint16)
    	fmt.Printf("uint32 length: %v range: 0 ~ %v\n", unsafe.Sizeof(uint32(1)), math.MaxUint32)
    	fmt.Printf("uint64 length: %v range: 0 ~ %v\n", unsafe.Sizeof(uint64(1)), uint64(math.MaxUint64))
    	fmt.Printf("uint   length: %v\n", unsafe.Sizeof(uint(1)))
    }
    

    输出:

    int8   length: 1 range: -128 ~ 127
    int16  length: 2 range: -32768 ~ 32767
    int32  length: 4 range: -2147483648 ~ 2147483647
    int64  length: 8 range: -9223372036854775808 ~ 9223372036854775807
    int    length: 8
    uint8  length: 1 range: 0 ~ 255
    uint16 length: 2 range: 0 ~ 65535
    uint32 length: 4 range: 0 ~ 4294967295
    uint64 length: 8 range: 0 ~ 18446744073709551615
    uint   length: 8
    

    有符号整形

    这种整形就是可以表示负整数,0和正整数

    数据类型 占用空间(bit) 长度(字节) 取值范围
    int8 8 1 -2^7 ~ 2^7-1(-128~127)
    int16 16 2 -2^15 ~ 2^15-1(-32768 ~ 32767)
    int32 32 4 -2^32 ~ 2^32-1(-2147483648 ~ 2147483647)
    int64 64 8 -2^64 ~ 2^64-1(-9223372036854775808 ~ 9223372036854775807)
    int 32或64 4或8 同int32或int64

    无符号整形

    这种整形就是可以表示非负整数

    数据类型 占用空间(bit) 长度(字节) 取值范围
    uint8 8 1 0 ~ 2^8-1(0 ~ 255)
    uint16 16 2 0 ~ 2^16-1(0 ~ 65535)
    uint32 32 4 0 ~ 2^32-1(0 ~ 4294967295)
    uint64 64 8 0 ~ 2^64-1(0 ~ 18446744073709551615)
    uint 32或64 4或8 同uint32或uint64

    浮点型

    浮点型在编程中可以表示一定范围内的实数

    注意:对于浮点型我们要关注的是数据类型的长度,数据范围,但更要关注精度。

    代码如下:

    package main
    
    import (
    	"fmt"
    	"math"
    	"unsafe"
    )
    
    func main() {
    	fmt.Printf("float32 length: %v range: %v ~ %v\n", unsafe.Sizeof(float32(1)), -math.MaxFloat32, math.MaxFloat32)
    	fmt.Printf("float64 length: %v range: %v ~ %v\n", unsafe.Sizeof(float64(1)), -math.MaxFloat64, math.MaxFloat64)
    	fmt.Printf("after transfer float32 %v\n", float32(1.328))
    	fmt.Printf("after transfer float64 %v\n", float64(float32(1.328)))
    }
    

    输出:

    float32 length: 4 range: -3.4028234663852886e+38 ~ 3.4028234663852886e+38
    float64 length: 8 range: -1.7976931348623157e+308 ~ 1.7976931348623157e+308
    before transfer float32: 1.328
    after  transfer float64: 1.3279999494552612
    

    你可以看到1.328在float32强制转化为float64反常地失去了一些精度,当然这就是为啥项目和数据库只有高精度实数的原因,你可以想象在这种情况时使用乘法后可怕的结果。

    至于这个产生的原因时浮点32型和浮点64型在计算机上表示方式不同,这部分内容你可以查看《计算机程序的构造和解释》。

    列表如下:

    数据类型 占用空间(bit) 长度(字节) 取值范围
    float32 32 4 -3.4028234663852886e+38 ~ 3.4028234663852886e+38
    float64 64 8 -1.7976931348623157e+308 ~ 1.7976931348623157e+308

    布尔型

    最简单的类型

    注意:分支语句中的if后面的表达式的结果值是true或false

    代码如下:

    package main
    
    import (
    	"fmt"
    	"unsafe"
    )
    
    func main() {
    	fmt.Printf("bool length: %v %v/%v", unsafe.Sizeof(true), 0 == 0, 0 != 0)
    }
    

    输出:

    bool length: 1 true/false
    

    列表如下:

    数据类型 占用空间(bit) 长度(字节) 取值范围
    bool 1 1 true/false

    字符

    注意:byte是包含ascii码,即uint8 ,rune是可以包含utf-8的,即uint32

    代码如下:

    package main
    
    import (
    	"fmt"
    	"unsafe"
    )
    
    func main() {
    	fmt.Printf("byte length: %v %v %c\n", unsafe.Sizeof(byte('a')),byte('a'),byte('a'))
    	fmt.Printf("rune length: %v %v %c\n", unsafe.Sizeof(rune('中')),rune('中'),rune('中'))
    }
    

    输出:

    byte length: 1 97 a
    rune length: 4 20013

    列表如下:

    数据类型 占用空间(bit) 长度(字节) 取值范围
    byte 8 1 0 ~ 2^8-1(0 ~ 255)
    rune 32 4 0 ~ 2^32-1(0 ~ 4294967295)

    本篇小结

    很好,你已经阅读完了go的基本数据类型!看是不是简单?学习go语言其实比较简单,你先通过例题知道了选择基础数据类型的重要性,然后通过基本数据类型,你知道了每个类型都有自己的长度,取值范围和注意点,最后相关代码房子在go语言学习的go-base/2中,你需要编写这些代码来实践一下go语言。

    下一篇预告

    go语言的控制结构

  • 相关阅读:
    libtorch之cv::Mat和Tensor的互转
    Spring框架系列(6) - Spring IOC实现原理详解之IOC体系结构设计
    【JavaWeb】数据库连接池
    Django(八、如何开启事务、介绍长见的字段类型和参数)
    opencv调用yolov7 yolov7 c++ yolov7转onnx opencv调用yolov7 onnx
    Spring之bean的生命周期
    基础复习——为activity补充活动信息——利用资源文件配置字符串——利用元数据传递配置信息——给页面注册快捷方式...
    go~在阿里mse上使用redis.call
    Debezium系列之:永久保存history topic中的数据
    【大道模式】状态模式 - State Pattern(审核状态流转)
  • 原文地址:https://www.cnblogs.com/onlyac/p/17642741.html