zoukankan      html  css  js  c++  java
  • 4.5 基本类型和运算符

    整型 int 和浮点型 float

    Go 语言支持整型和浮点型数字,并且原生支持复数,其中位的运算采用补码(详情参见 二的补码 页面)。

    Go 也有基于架构的类型,例如:int、uint 和 uintptr。

    这些类型的长度都是根据运行程序所在的操作系统类型所决定的:

    • int 和 uint 在 32 位操作系统上,它们均使用 32 位(4 个字节),在 64 位操作系统上,它们均使用 64 位(8 个字节)。
    • uintptr 的长度被设定为足够存放一个指针即可。

    Go 语言中没有 float 类型。

    与操作系统架构无关的类型都有固定的大小,并在类型的名称中就可以看出来:

    整数:

    • int8(-128 -> 127)
    • int16(-32768 -> 32767)
    • int32(-2,147,483,648 -> 2,147,483,647)
    • int64(-9,223,372,036,854,775,808 -> 9,223,372,036,854,775,807)

    无符号整数:

    • uint8(0 -> 255)
    • uint16(0 -> 65,535)
    • uint32(0 -> 4,294,967,295)
    • uint64(0 -> 18,446,744,073,709,551,615)

    浮点型(IEEE-754 标准):

    • float32(+- 1e-45 -> +- 3.4 * 1e38)
    • float64(+- 5 * 1e-324 -> 107 * 1e308)

    int 型是计算最快的一种类型。

    整型的零值为 0,浮点型的零值为 0.0。

    float32 精确到小数点后 7 位,float64 精确到小数点后 15 位。由于精确度的缘故,你在使用 == 或者 != 来比较浮点数时应当非常小心。你最好在正式使用前测试对于精确度要求较高的运算。

    你应该尽可能地使用 float64,因为 math 包中所有有关数学运算的函数都会要求接收这个类型。

    你可以通过增加前缀 0 来表示 8 进制数(如:077),增加前缀 0x 来表示 16 进制数(如:0xFF),以及使用 e 来表示 10 的连乘(如: 1e3 = 1000,或者 6.022e23 = 6.022 x 1e23)。

    你可以使用 a := uint64(0) 来同时完成类型转换和赋值操作,这样 a 的类型就是 uint64。

    Go 中不允许不同类型之间的混合使用,但是对于常量的类型限制非常少,因此允许常量之间的混合使用

    package main
    
    import "fmt"
    
    func main() {
        /*
            var a int
            var c int32
            a = 15
            b = a + a // 编译错误cannot use a + a (type int) as type int32 in assignment
            c = b + b
            c = c + 5 // 因为 5 是常量,所以可以通过编译
        */
        var n int16 = 34
        var m int32
        var b float64 = 789.11111
        // compiler error: cannot use n (type int16) as type int32 in assignment
        //m = n
        m = int32(n)
    
        fmt.Printf("32(m) bit int is: %d
    ", m)
    
        fmt.Printf("16(n) bit int is: %d
    ", n)
    
        //%0.3f(%n.m[f,g,e]) 保留小数点3位,用于表示数字 n 并精确到小数点后 m 位
        fmt.Printf("64(b) bit float is: %0.3f
    ", b)
    }

    这里在写一个类型转换案例:

    int转成uint8和float64 转int32

    package main
    
    import "fmt"
    import "math"
    
    func main() {
        var n int = 100
    //math 都是基于float64来写的所以这里计算就都用64的 var j float64 = 100.6 //结果返回2个参数这里就必须用2个变量来接收结果 result, err := Uint8FromInt(n) fmt.Println(result, err) resul_int := IntFromFloat64(j) fmt.Println("IntFromFloat64:", resul_int) } /*将int安全的转成uint8,函数名Uint8FromInt指定参数和参数类型(n int) 指定返回的类型(uint8, error)*/ func Uint8FromInt(n int) (uint8, error) { //math.MaxUint8 这个就是Uint8最大的值255,16是65535 。满足2个条件的时候为真 if 0 <= n && n <= math.MaxUint8 { // conversion is safe //返回数据的时候必须符合定义(uint8, error)的类型 return uint8(n), nil } //0这里没有指定类型,uint8包括0所以这里没有报错。 return 0, fmt.Errorf("%d is out of the uint8 range", n) } func IntFromFloat64(x float64) int { //int32是有符号的所以这个范围就是max和min if math.MinInt32 <= x && x <= math.MaxInt32 { // x lies in the integer range //math.Modf(x)返回2个结果 :whole整数部分,fraction小数部分。 whole, fraction := math.Modf(x) //小数部分大于0.5为真 if fraction >= 0.5 { //下面的这个等于这个whole = whole + 1 whole++ } return int(whole) } panic(fmt.Sprintf("%g is out of the int32 range", x)) }

    结果:

    一元运算符

    • 按位补足 ^

      该运算符与异或运算符一同使用,即 m^x,对于无符号 x 使用“全部位设置为 1”,对于有符号 x 时使用 m=-1。例如:

      ^2 = ^10 = -01 ^ 10 = -11
    • 位左移 <<

      • 用法:bitP << n
      • bitP 的位向左移动 n 位,右侧空白部分使用 0 填充;如果 n 等于 2,则结果是 2 的相应倍数,即 2 的 n 次方。例如:

        1 << 10 // 等于 1 KB
        1 << 20 // 等于 1 MB
        1 << 30 // 等于 1 GB
    • 位右移 >>

      • 用法:bitP >> n
      • bitP 的位向右移动 n 位,左侧空白部分使用 0 填充;如果 n 等于 2,则结果是当前值除以 2 的 n 次方。

    当希望把结果赋值给第一个操作数时,可以简写为 a <<= 2 或者 b ^= a & 0xffffffff

    位左移常见实现存储单位的用例

    使用位左移与 iota 计数配合可优雅地实现存储单位的常量枚举:

      

    package main
    
    import "fmt"
    
    type ByteSize float64
    
    //1.048576e+06
    const (
        _           = iota // 通过赋值给空白标识符来忽略值
        KB ByteSize = 1 << (10 * iota)
        MB
        GB
        TB
        PB
        EB
        ZB
        YB
    )
    
    func main() {
        //这里是2的10次方,第一次iota为空KB=1024字节,MB=1024*1024(个人理解iota=1024)
        fmt.Println("KB:", KB)
        fmt.Println("MB:", MB)
        fmt.Println("GB:", GB)
    }

    结果:可以把数换小一点这样可以很简单的看出效果

    在来一个应用实例:

    package main
    
    import "fmt"
    
    type ByteSize float64
    
    type BitFlag int
    
    const (
        Active  BitFlag = 11 << iota // 1 << 0 == 1
        Send                         // 1 << 1 == 2
        Receive                      // 1 << 2 == 4
        test
    )
    
    func main() {
        //Active + Send + Receive=7
        flag := Active | Send | Receive
        /*
                这里用的是2的倍数,第一次iota 没有值,1 、2 、4、8、16、32、64"1 <<"开始的数 ,如果起始数是3:3、6、12、24、48
        */fmt.Println("flag:", Active)
        fmt.Println("flag:", Send)
        fmt.Println("flag:", Receive)
        fmt.Println("flag:", test)
        fmt.Println("flag:", flag)
    }

    结果:

    算术运算符

    常见可用于整数和浮点数的二元运算符有 +-* 和 /

    (相对于一般规则而言,Go 在进行字符串拼接时允许使用对运算符 + 的重载,但 Go 本身不允许开发者进行自定义的运算符重载)

    / 对于整数运算而言,结果依旧为整数,例如:9 / 4 -> 2

    取余运算符只能作用于整数:9 % 4 -> 1

    整数除以 0 可能导致程序崩溃,将会导致运行时的恐慌状态(如果除以 0 的行为在编译时就能被捕捉到,则会引发编译错误)

    浮点数除以 0.0 会返回一个无穷尽的结果,使用 +Inf 表示:

    你可以将语句 b = b + a 简写为 b+=a,同样的写法也可用于 -=*=/=%=

    对于整数和浮点数,你可以使用一元运算符 ++(递增)和 --(递减),但只能用于后缀:

         同时,带有 ++ 和 -- 的只能作为语句,而非表达式,因此 n = i++ 这种写法是无效的,其它像 f(i++) 或者 a[i]=b[i++]这些可以用于 C、C++ 和 Java 中的写法在 Go 中也是不允许的。

    在运算时 溢出 不会产生错误,Go 会简单地将超出位数抛弃。如果你需要范围无限大的整数或者有理数(意味着只被限制于计算机内存),你可以使用标准库中的 big 包,该包提供了类似 big.Int 和 big.Rat 这样的类型

    package main
    
    import "fmt"
    
    func main() {
    
        a := 1
        a++    //这样 OK,但是不能b := a++
        a += a //这样写是OK的
        fmt.Println("a:", a)
    }

    随机数

    一些像游戏或者统计学类的应用需要用到随机数。rand 包实现了伪随机数的生成。

    package main
    
    import (
        "fmt"
        "math/rand"
        "time"
    )
    
    func main() {
        //i++真的等于i += i?有兴趣的可以试试,随机三组数
        for i := 0; i < 3; i++ {
            a := rand.Int()
            if i == 2 {
                fmt.Printf("%d  
    ", a)
            } else {
                fmt.Printf("%d / ", a)
            }
        }
        //从0-8中随机
        for i := 0; i < 3; i++ {
            r := rand.Intn(8)
            if i == 2 {
                fmt.Printf("%d  
    ", r)
            } else {
                fmt.Printf("%d / ", r)
            }
        }
        //随机浮点数
        timens := int64(time.Now().Nanosecond())
        rand.Seed(timens)
        for i := 0; i < 3; i++ {
            fmt.Printf("%0.3f / ", 100*rand.Float32())
        }
    }

    输出:

    运算符与优先级

    当然,你可以通过使用括号来临时提升某个表达式的整体运算优先级

    引入包来计算 :

    目录结构(这个跟python差不多,但是很多新手会出错):

     init包代码,init函数是在main函数之前执行的,注意看 "package"名字。写的是目录的名字

    package test
    
    import "math"
    
    var Pi float64
    
    func init() {
        Pi = 2 * math.Atan(1) // init() function computes Pi
    }

    test.go文件内容

    package main
    
    import (
        "fmt"
    
        "./test"
    )
    
    func main() {
        fmt.Println(test.Pi + 100)
    }

    执行结果:

  • 相关阅读:
    sharepoint具体错误提示
    体验魅力Cognos BI 10 系列,第1 部分: 第一次安装
    Moss、SharePoint数据库迁移问题(转)
    XML解析
    JDBC进阶
    JDBC的操作
    项目Contact开发中遇到的,引以为戒
    递归练习
    递归详解(四)
    递归详解(三)
  • 原文地址:https://www.cnblogs.com/menkeyi/p/6093390.html
Copyright © 2011-2022 走看看