使用math.Float64bits()
您可以使用math.Float64bits()
函数,该函数返回一个uint64
值,其字节/位与传递给它的float64
值相同。
一旦您有了一个uint64
,在其上执行按位操作是微不足道的:
f := 1.0 // Some float64 value
bits := math.Float64bits(f)
if f >= 0 {
bits ^= 0x8000000000000000
} else {
bits ^= 0xffffffffffffffff
}
然后将 f
float64 值代替为 bits
值进行序列化,就完成了。
让我们看看这个过程。我们创建一个包装类型来保存一个 float64
数字及其字节:
type num struct {
f float64
data [8]byte
}
让我们创建这些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)
}
}
这是我们如何按字节排序它们的方法:
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
} else if bi > bj {
return false
}
}
return false
})
现在让我们看一下按字节排序后的顺序:
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
值序列化,然后对字节执行 XOR 操作。
如果数字是正数(或零),则将第一个字节与 0x80
进行 XOR,其余字节与 0x00
进行 XOR,这基本上不会对它们进行任何操作。
如果数字是负数,则将所有字节与 0xff
进行 XOR,这基本上是按位取反。
实际应用中:唯一不同的部分是序列化和 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
}
}
}
其余的部分都是一样的。输出结果也是相同的。在
Go Playground上尝试一下。
[]byte
,而没有原始数字,因此我创建了这两个函数:```func flipFloat(b []byte) []byte { if b[0]>>7 > 0 { for i, bb := range b { b[i] = ^bb } } else { b[0] ^= 0x80 } return b }func flipFloatBack(b []byte) []byte { if b[0]>>7 > 0 { b[0] ^= 0x80 } else { for i, bb := range b { b[i] = ^bb } } return b }``` - jpincas