天天看點

golang之資料轉換

  1. golang按位取反符号和異或符号都是^。
fmt.Printf("0x%X\n", 0xFF^0x55)
var a uint8 = 0x55
fmt.Printf("%b\n", ^a)      

要限定類型或位數,否則按int列印(列印負數)。

  1. 資料存儲編解碼

float32儲存為4個位元組,int16存儲為兩個位元組,資料大小端怎樣存儲?

參考:edgexfoundry/device-sdk-go/pkg/commandvalue.go

借助io.Reader,int16和float32限定了資料存儲的位元組數。

func encodeValue(value interface{}) ([]byte, error) {
    buf := new(bytes.Buffer)
    err := binary.Write(buf, binary.LittleEndian, value)
    return buf.Bytes(), err
}

func decodeValue(reader io.Reader, value interface{}) error {
    err := binary.Read(reader, binary.LittleEndian, value)
    return err
}

func float32Value(buf []byte) (value float32, err error) {
    err = decodeValue(bytes.NewReader(buf), &value)
    return value, err
}

func int16Value(buf []byte) (value int16, err error) {
    err = decodeValue(bytes.NewReader(buf), &value)
    return value, err
}

func uint16Value(buf []byte) (value uint16, err error) {
    err = decodeValue(bytes.NewReader(buf), &value)
    return value, err
    }

func main(){
    var ff float32 = 100.5
    ffb, err := encodeValue(ff)
    if err != nil {
        fmt.Println(err)
    } else {
        fmt.Println(ffb)
    }

    fmt.Println("------------------")
    ffn, err := float32Value(ffb)
    if err != nil {
        fmt.Println(err)
    } else {
        fmt.Println(ffn)
    }

    fmt.Println("----------------------------------")
    var us uint16 = 0xFFF1
    usb , err := encodeValue(us)
    if err != nil {
        fmt.Println(err)
    } else {
        fmt.Println(usb)
    }
    fmt.Println("------------------")
    usn, err := uint16Value(usb)
    if err != nil {
        fmt.Println(err)
    } else {
        fmt.Printf("0x%X\n", usn)
        var mask uint16 = 0x1
        var maskv uint16 = 0x0
        usn = usn & (^mask) | mask
        fmt.Printf("0x%X\n", usn)
        usn = usn & (^mask) | maskv
        fmt.Printf("0x%X\n", usn)
    }
}      
  1. float資料精度轉換

參考:​​https://studygolang.com/articles/22284​​中浮點數比較

golang支援兩種浮點float32和float64,衆所周知,涉及浮點數比較或運算會遇到精度問題,具體要根據golang實作IEEE 754的情況定。

預設情況下,float32精度是小數後7位,float64精度是小數後15位。浮點數比較時取精度範圍内的資料,範圍外根據存儲情況五舍六入(5實際存儲時可能是5.9舍,可能是5.99入)。

package main

import (
    "fmt"
)

func main(){
    var a float32 =     1.0000001
    var b float32 =     1.00000001
    var bb float32 =    1.00000005
    var bbb float32 =   1.00000006
    var c float32 =     1.00000000000001

    fmt.Println(a == b) // false
    fmt.Println(a == bb) // false
    fmt.Println(b == bb) // true
    fmt.Println(b == c) // true
    fmt.Println(bb == c)// true
    fmt.Println(a == bbb) // true
    fmt.Println(bb == bbb) // false
}      

小數點後保留兩位小數:

func updateFloatPrecision(sf string, pre int, bitSize int) (sfp string, err error){
    ff, err := strconv.ParseFloat(sf, bitSize)
    if err != nil {
        return sf, err
    }
    sfp = strconv.FormatFloat(float64(ff), 'f', pre, bitSize)
    return sfp, nil
}

    sfp := "-3.1415926"
    sfp, err := updateFloatPrecision(sfp, 2, 32)
    if err != nil {
        fmt.Println(err)
    } else {
        fmt.Println(sfp)
    }
或
sfp, _ :=updateFloatPrecision(sfp, 2, 32)
fmt.Prinln(sfp)
因為函數錯誤時傳回原來字元串,成功後傳回正确的字元串,符合現實習慣      
  1. golang最大數值

math包定義了最大數值。​​https://golang.google.cn/pkg/math/​​

Floating-point limit values. Max is the largest finite value representable by the type. SmallestNonzero is the smallest positive, non-zero value representable by the type.
const (
    MaxFloat32             = 3.40282346638528859811704183484516925440e+38  // 2**127 * (2**24 - 1) / 2**23
    SmallestNonzeroFloat32 = 1.401298464324817070923729583289916131280e-45 // 1 / 2**(127 - 1 + 23)

    MaxFloat64             = 1.797693134862315708145274237317043567981e+308 // 2**1023 * (2**53 - 1) / 2**52
    SmallestNonzeroFloat64 = 4.940656458412465441765687928682213723651e-324 // 1 / 2**(1023 - 1 + 52)
)
Integer limit values.
const (
    MaxInt8   = 1<<7 - 1
    MinInt8   = -1 << 7
    MaxInt16  = 1<<15 - 1
    MinInt16  = -1 << 15
    MaxInt32  = 1<<31 - 1
    MinInt32  = -1 << 31
    MaxInt64  = 1<<63 - 1
    MinInt64  = -1 << 63
    MaxUint8  = 1<<8 - 1
    MaxUint16 = 1<<16 - 1
    MaxUint32 = 1<<32 - 1
    MaxUint64 = 1<<64 - 1
)      

參考:golang最大無符号數

對于不确定位數的uint,最大的無符号數和-1在位數上是一樣的。但是,無論是 const MaxUint uint = -1 // Error: negative value , 還是const MaxUint uint = uint(-1) // Error: negative value,都不能通過編譯,原因自然是類型與範圍的沖突了。但運作時,-1的值确實可以傳遞給無符号是,怎麼通過編譯,又将這個值傳給無符号數呢?可以

var u uint
var v = -1
u = uint(v)      

這樣就搞定了。另一種方法就是對0取反。差別是,0取反後,是無限多個1,那麼有限範圍的uint去接它,顯然會被編譯器認為損失精度了。辦法是先構造出确定位數的0,再取反,如下:

const MaxUint = ^uint(0)      

這便是兩種獲得最大無符号數的方法了。

  1. more

參考:

  1. https://studygolang.com/articles/22284

    golang不同類型比較

  2. https://studygolang.com/articles/5567

    golang最大無符号數