从两个值生成唯一的ID
从两个值中产生一个唯一的数字(比如说一个64位无符号整数)是一种惯用的方式,以这种方式可以从数字中重新生成输入值(也是同一类型的数字),如Haskell函数?
在C / C ++上,我可能会使用类似的东西
result = (((value1) << BITS) + ((value2) & ((1 << BITS) - 1)))
并因此,
value1 = (result >> BITS)
和
value2 = (result & ((1 << BITS) - 1))
重新生成值,但我不认为我应该尝试在Haskell中使用按位运算。
经过考虑,我简单地放弃了使用按位操作的想法,并采用了Cantor的配对功能:
pair :: (Fractional a) => a -> a -> a
pair x y = (1 / 2) * (x + y) * (x + y + 1) + y
unpair :: (RealFrac a, Floating a) => a -> (a, a)
unpair z = (x, y) where
q = (-1 / 2) + sqrt (1 / 4 + 2 * z)
j = fromInteger (truncate q)
y = z - ((1 / 2) * j * (j + 1))
x = j - y
这可能是我从一开始就应该考虑的方式。 不过,非常感谢您帮助我更好地理解Haskell的一些操作。
你可以在Haskell中使用完全相同的方式。 按位操作可以在Data.Bits
和Data.Bits
无符号,固定大小的整数类型中Data.Word
。 例如:
import Data.Bits
import Data.Word
combine :: Word32 -> Word32 -> Word64
combine a b = (fromIntegral a `shiftL` 32) + fromIntegral b
separate :: Word64 -> (Word32, Word32)
separate w = (fromIntegral $ w `shiftR` 32, fromIntegral $ w .&. 0xffff)
与C相比,可能会让你感觉不舒服的是Haskell不会隐式地在不同的数字类型之间进行转换,因此您需要使用fromIntegral
来在例如32位和64位无符号整数之间进行转换。