在F#中反转位

时间:2016-05-20 20:48:10

标签: f# bits

我需要帮助翻转F#中的位,就像在这个问题Reverse bits in number中所做的那样。我是F#的新手,想知道我们怎么做到这一点?

let bitreverse x = 
   let mutable b = 0
       while x do 
          b >>>= 1
          b|= x & 1
          x >>>= 1
b

我甚至不确定这里的语法是否正确。我非常了解这种语言。

2 个答案:

答案 0 :(得分:4)

直接翻译成F#看起来像这样:

let bitreverse x = 
    let mutable x = x
    let mutable b = 0
    while x <> 0 do 
        b <- b <<< 1
        b <- b ||| (x &&& 1)
        x <- x >>> 1
    b

这对于可变值非常重要,这通常不是我们在F#中编写代码的方式。请注意,重新分配可变变量与您在命令式语言中使用的变量略有不同,您必须使用称为破坏性更新运算符的<-

值得庆幸的是,将它转换为使用不可变值的递归函数非常简单,这些值应该更加惯用

let bitreverse2 x =
    let rec bitRerverseHelper b x =
        match x with
        |0 -> b // if 0, the recursion stops here and we return the result: b
        |_ -> bitRerverseHelper ((b <<< 1) ||| (x &&& 1)) (x >>> 1) // otherwise recurse
    bitRerverseHelper 0 x

答案 1 :(得分:3)

  1. F#不支持复合赋值,因此您无法执行b |= x & 1之类的操作,需要将其展开为b <- b ||| (x &&& 1)
  2. 参数x不可变,因此您需要创建一个本地绑定并对其进行变异。它看起来很奇怪,但你可以写let mutable x = x作为函数的第一行,用可变的阴影来遮蔽现有的绑定。
  3. x是一个int,而不是bool,因此您不能将它用作while循环的条件。请改用x <> 0
  4. 缩进在F#中很重要,因此请确保while和您的最终b都与第一个let对齐。
  5. 修复这些问题会使你的代码工作,但惯用的F#可能会放弃while循环和变异,而是使用带累加器的递归内部函数。