1 回答

TA貢獻(xiàn)1859條經(jīng)驗 獲得超6個贊
使用math.Float64bits()
您可以使用math.Float64bits()
which 返回一個與傳遞給它的uint64
值具有相同字節(jié)/位的值float64
。
一旦有了uint64
,對其執(zhí)行按位運算就很簡單了:
f := 1.0 // Some float64 value
bits := math.Float64bits(f)
if f >= 0 {
? ? bits ^= 0x8000000000000000
} else {
? ? bits ^= 0xffffffffffffffff
}
然后序列化該bits值而不是ffloat64 值,就大功告成了。
讓我們看看實際效果。float64讓我們創(chuàng)建一個包含數(shù)字及其字節(jié)的包裝器類型:
type num struct {
? ? f? ? float64
? ? data [8]byte
}
讓我們創(chuàng)建這些 s 的一部分num:
nums := []*num{
? ? {f: 1.0},
? ? {f: 2.0},
? ? {f: 0.0},
? ? {f: -1.0},
? ? {f: -2.0},
? ? {f: math.Pi},
}
序列化它們:
for _, n := range nums {
? ? bits := math.Float64bits(n.f)
? ? if n.f >= 0 {
? ? ? ? bits ^= 0x8000000000000000
? ? } else {
? ? ? ? bits ^= 0xffffffffffffffff
? ? }
? ? if err := binary.Write(bytes.NewBuffer(n.data[:0]), binary.BigEndian, bits); err != nil {
? ? ? ? panic(err)
? ? }
}
這就是我們?nèi)绾伟醋止?jié)對它們進(jìn)行排序:
sort.Slice(nums, func(i int, j int) bool {
? ? ni, nj := nums[i], nums[j]
? ? for k := range ni.data {
? ? ? ? if bi, bj := ni.data[k], nj.data[k]; bi < bj {
? ? ? ? ? ? return true // We're certain it's less
? ? ? ? } else if bi > bj {
? ? ? ? ? ? return false // We're certain it's not less
? ? ? ? } // We have to check the next byte
? ? }
? ? return false // If we got this far, they are equal (=> not less)
})
現(xiàn)在讓我們看看按字節(jié)排序后的順序:
fmt.Println("Final order byte-wise:")
for _, n := range nums {
? ? fmt.Printf("% .7f %3v\n", n.f, n.data)
}
輸出將是(在Go Playground上嘗試):
Final order byte-wise:
-2.0000000 [ 63 255 255 255 255 255 255 255]
-1.0000000 [ 64? 15 255 255 255 255 255 255]
?0.0000000 [128? ?0? ?0? ?0? ?0? ?0? ?0? ?0]
?1.0000000 [191 240? ?0? ?0? ?0? ?0? ?0? ?0]
?2.0000000 [192? ?0? ?0? ?0? ?0? ?0? ?0? ?0]
?3.1415927 [192? ?9? 33 251? 84? 68? 45? 24]
沒有math.Float64bits()
另一種選擇是先序列化float64值,然后對字節(jié)執(zhí)行異或運算。
如果數(shù)字是正數(shù)(或零),則第一個字節(jié)與 異或0x80,其余字節(jié)與 異或0x00,這基本上對它們什么都不做。
如果數(shù)字是負(fù)數(shù),則將所有字節(jié)與 異或0xff,這基本上是按位求反。
實際上:唯一不同的部分是序列化和 XOR 操作:
for _, n := range nums {
? ? if err := binary.Write(bytes.NewBuffer(n.data[:0]), binary.BigEndian, n.f); err != nil {
? ? ? ? panic(err)
? ? }
? ? if n.f >= 0 {
? ? ? ? n.data[0] ^= 0x80
? ? } else {
? ? ? ? for i, b := range n.data {
? ? ? ? ? ? n.data[i] = ^b
? ? ? ? }
? ? }
}
其余的是一樣的。輸出也將相同。
- 1 回答
- 0 關(guān)注
- 270 瀏覽
添加回答
舉報