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.Readerint16float32限定了数据存储的字节数。

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支持两种浮点float32float64,众所周知,涉及浮点数比较或运算会遇到精度问题,具体要根据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最大无符号数

posted @ 2019-12-08 17:36  yuxi_o  阅读(824)  评论(0编辑  收藏  举报