Ocaml 将64位浮点转换为位列表的更简单方法

Ocaml 将64位浮点转换为位列表的更简单方法,ocaml,Ocaml,我正在尝试将浮点转换为位列表 以下是我的想法: 从float读取所有位信息到Int64 mod 264次,每次将0或1存储到列表中 处理否定的情况(应用2的补码加1) 代码如下所示: let convert_non_neg_64 n = let rec collect acc i j = if Int64.compare j (Int64.of_int 64) <> -1 then acc else collect ((Int64.rem i (Int64.of_

我正在尝试将浮点转换为位列表

以下是我的想法:

  • float
    读取所有位信息到
    Int64
  • mod 2
    64次,每次将
    0
    1
    存储到列表中
  • 处理否定的情况(应用2的补码加1)
  • 代码如下所示:

    let convert_non_neg_64 n =
      let rec collect acc i j =
        if Int64.compare j (Int64.of_int 64) <> -1 then acc
        else collect ((Int64.rem i (Int64.of_int 2) |> Int64.to_int)::acc) (Int64.div i (Int64.of_int 2)) (Int64.succ j)
      in 
      collect [] n Int64.zero
    
    let negatify l =
      let rl = List.rev_map (fun x -> if x = 0 then 1 else 0) l in
      let rec plus1 extra acc = function
        | [] -> acc
        | hd::tl when extra = 0 -> plus1 0 (hd::acc) tl
        | hd::tl -> if hd = 0 then plus1 0 (1::acc) tl else plus1 1 (0::acc) tl
      in 
      plus1 1 [] rl
    
    let convert64 n =
      let nnl = convert_non_neg_64 (Int64.abs n) in 
      if Int64.compare n Int64.zero <> -1 then nnl
      else negatify nnl
    
    let bits_of_float fn = Int64.bits_of_float fn |> convert64 
    
    让我们转换为非负=
    让rec收集acc i j=
    如果Int64.compare j(Int64.of_int 64)-1,则acc
    else collect((Int64.remi(Int64.of_int 2)|>Int64.to_int)::acc)(Int64.div i(Int64.of_int 2))(Int64.such j)
    在里面
    收集[]n Int64.zero
    让我们否定l=
    让rl=List.rev_映射(funx->如果x=0,则为1,否则为0)l进入
    让rec plus1额外acc=功能
    |[]->acc
    |额外=0时的hd::tl->plus1 0(hd::acc)tl
    |hd::tl->如果hd=0,则加上10(1::acc)tl,否则加上1(0::acc)tl
    在里面
    加1[]rl
    让我们来看一看=
    设nnl=在中转换非负64(Int64.abs n)
    如果Int64.0与Int64.0-1比较,则nnl
    否则否定nnl
    设浮点数fn的位=Int64。浮点数fn的位>convert64
    

    我认为代码很好

    我的问题是有没有更简单的方法


    而且,所有那些
    Int64
    操作都非常难看,有什么好方法可以简化吗?

    这就是我想到的

    let bitlist_of_float f =
        let rec blist b i64 =
            if b >= 64 then
                []
            else
                let bit =
                    Int64.(if logand i64 (shift_left 1L b) = 0L then 0 else 1)
                in
                bit :: blist (b + 1) i64
        in  
        blist 0 (Int64.bits_of_float f)
    
    榜首是最不重要的一位(我认为这是正确的做事方式)。我还没有验证答案,所以可能有一两个错误

    更新


    我相信这段代码会给你一些浮点值。这就是我所说的“忠实副本”的全部意思。如果你想以某种方式修改这些位,那么你需要对它们进行更多的工作。我不知道你想用它们做什么。

    Int64
    实际上并不是要打开的那种模块,但是你总是可以围绕最需要它的表达式编写
    Int64。(……
    在你编写
    Int64.compare n Int64.zero-1
    你的意思是
    Int64.compare n Int64.zero>=0
    (您可以编写
    Int64.(compare n zero)>=0
    )。不应假定
    compare
    函数返回-1或1。
    Int64.compare j(Int64.of_int 64)的最简单表达式-1
    j>=64L
    。我不明白你为什么需要特别处理负片。如果你使用位运算,你不需要关心数值。Int64.logand可以检查低位(或任何位)。@JeffreyScofield你是什么意思?我认为负片的位表示不同?我正在尝试实现这一点