nat base 10在哪里转换为num base 2?

时间:2014-06-07 15:17:17

标签: isabelle

对于term "15::nat",值15会自动转换为二进制值(num.Bit1 (num.Bit1 (num.Bit1 num.One)))。我想知道它在哪里完成,所以我可以知道它是如何完成的。

小更新:我知道15是一个类型类numeral常量,它被转换为二进制Num.num,它被映射到nat,所以也许nat是小数,也可能是二进制。但是,我的基本问题仍然是一样的。十进制到二进制转换在哪里完成?)

我在下面展示了解转换的方式。

我定义了符号,告诉我Num.numeral :: (num => 'a)正在强制转换为Num.num

abbreviation nat_of_numeral :: "num => nat" where
  "nat_of_numeral n == (numeral n)"

notation nat_of_numeral ("n@N|_" [1000] 1000)

接下来,在term命令中将15强制转换为二进制文件:

term "15::nat"
(*The output:*)
term "n@N|(num.Bit1 (num.Bit1 (num.Bit1 num.One))) :: nat"

接下来,15在被证明目标使用之前被强迫:

lemma "15 = n@N|(num.Bit1 (num.Bit1 (num.Bit1 num.One)))" (*
  goal (1 subgoal):
   1. n@N|(num.Bit1 (num.Bit1 (num.Bit1 num.One))) =
      n@N|(num.Bit1 (num.Bit1 (num.Bit1 num.One))) *)
by(rule refl)

转换速度似乎相当快,如下所示:

(*140 digits: 40ms*)
term "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
  ::nat"

我还想将base 2转换为base 10,但是如果我看到上面的内容是如何完成的,它可能会告诉我如何做到这一点。

1 个答案:

答案 0 :(得分:0)

以下是我认为已经完成的概述。

它始于Num.thy parse_translation,位于ML函数numeral_tr

在该函数中,使用Lexicon.read_xnum of lexicon.ML,它接受​​一个字符串参数。

我不知道细节,但字符串"15"是从类似

的表达式中提取的
  "15 = n@N|(num.Bit1 (num.Bit1 (num.Bit1 num.One)))",

并提供给read_xnum,其中存在等效性:

  Lexicon.read_xnum "15" = {leading_zeros = 0, radix = 10, value = 15}

read_xnum中使用函数Library.read_radix_int of library.ML,它将整数基数和数字列表作为参数,如等效性所示:

  Library.read_radix_int 10 ["1","5"] = (15, []);

接下来,从15(num.Bit1 (num.Bit1 (num.Bit1 num.One)))的转换是IntInf.quotRem in the parse_translation的结果。

这使我不再使用isabelle.in.tum.de/repos的便捷HTML链接。

IntInf.quotRem位于Isabelle2013-2 \ contrib \ polyml-5.5.1-1 \ src \ basis \ IntInf.sml中,定义为

  val quotRem: int*int->int*int = RunCall.run_call2C2 POLY_SYS_quotrem,

导致Isabelle2013-2 \ contrib \ polyml-5.5.1-1 \ src \ basis \ RuntimeCalls.ML第83行:

  val POLY_SYS_quotrem = 104 (* DCJM 05/03/10 *).

对于将我带到Isabelle2013-2 \ contrib \ polyml-5.5.1-1 \ src \ libpolyml \ x86asm.asm第1660行的Windows,虽然我可能会遗漏一些重要的细节:

  quotrem_really_long:
    MOVL    Reax,Redi
  CALLMACRO   CALL_IO    POLY_SYS_quotrem
  CALLMACRO   RegMask quotrem,(M_Reax OR M_Redi OR M_Redx OR Mask_all).

我认为这足以回答我的问题。将字符串“15”转换为ML整数,然后使用某些汇编语言级别商/余数除法将15转换为二进制Num.num

我实际上只对“{1}}中如何将”15“转换为15感兴趣,以及该函数的详细信息是否对我有帮助。我将在下面详细解释该应用程序。

从这里开始,我为自己提供了更多详细信息,以便将我收集到的大量信息整理好。

什么样的交易

我从二进制数开始为read_radix_int,类似于bool list的二进制数15,不过在这里,我在某些方面简化了它。

然后转换为[True, True, True, True],即十进制15。

真正的问题可能是找到正确的搜索短语

搜索"decimal to binary conversion"之类的内容会返回许多基本数学算法的链接,而这些算法并不是我想要的。

正常的编程转换也不是我需要的,这只是明确了整数已经是二进制形式的基本事实:

最后,其他搜索让我找到了正确的词“radix”。另外,我使用C来搜索事情是如何完成的,其中位移是我想要的结果,尽管这些可能不是我需要的:

Radix回到Num.thy

“Radix”把我带回Num.thy,这是我认为行动可能的地方,但没有看到任何对我来说很明显的事情。

我包含了来自Num.thy,lexicon.ML和IntInf.sml的一些来源:

[[True, False, True, False], [True, False, True]]

我所寻找的很大一部分内容;基数

(* THE TWO MAIN EXTERNAL FUNCTIONS IN THE TRANSLATIONS: read_xnum, quotRem *)
ML{* 
  Lexicon.read_xnum;       (* string -> 
                               {leading_zeros: int, radix: int, value: int}.*)
  Lexicon.read_xnum "15";  (* {leading_zeros = 0, radix = 10, value = 15}.*)
  Lexicon.read_xnum "15" = {leading_zeros = 0, radix = 10, value = 15};

  IntInf.quotRem;          (* int * int -> int * int.*)
  IntInf.quotRem (5,3);    (* (1, 2) *)
*}

parse_translation {* (* Num.thy(293) *)
  let
    fun num_of_int n =
      if n > 0 then
        (case IntInf.quotRem (n, 2) of
          (0, 1) => Syntax.const @{const_name One}
        | (n, 0) => Syntax.const @{const_name Bit0} $ num_of_int n
        | (n, 1) => Syntax.const @{const_name Bit1} $ num_of_int n)
      else raise Match
    val pos = Syntax.const @{const_name numeral}
    val neg = Syntax.const @{const_name neg_numeral}
    val one = Syntax.const @{const_name Groups.one}
    val zero = Syntax.const @{const_name Groups.zero}
    fun numeral_tr [(c as Const (@{syntax_const "_constrain"}, _)) $ t $ u] =
          c $ numeral_tr [t] $ u
      | numeral_tr [Const (num, _)] =
          let
            val {value, ...} = Lexicon.read_xnum num;
          in
            if value = 0 then zero else
            if value > 0
            then pos $ num_of_int value
            else neg $ num_of_int (~value)
          end
      | numeral_tr ts = raise TERM ("numeral_tr", ts);
  in [("_Numeral", K numeral_tr)] end
*}

ML{* (* lexicon.ML(367) *)    
  (* read_xnum: hex/bin/decimal *)      
  local     
  val ten = ord "0" + 10;
  val a = ord "a";
  val A = ord "A";
  val _ = a > A orelse raise Fail "Bad ASCII";

  fun remap_hex c =
    let val x = ord c in
      if x >= a then chr (x - a + ten)
      else if x >= A then chr (x - A + ten)
      else c
    end;      
  fun leading_zeros ["0"] = 0
    | leading_zeros ("0" :: cs) = 1 + leading_zeros cs
    | leading_zeros _ = 0;      
  in      
  fun read_xnum str =
    let
      val (sign, radix, digs) =
        (case Symbol.explode (perhaps (try (unprefix "#")) str) of
          "0" :: "x" :: cs => (1, 16, map remap_hex cs)
        | "0" :: "b" :: cs => (1, 2, cs)
        | "-" :: cs => (~1, 10, cs)
        | cs => (1, 10, cs));
    in
     {radix = radix,
      leading_zeros = leading_zeros digs,
      value = sign * #1 (Library.read_radix_int radix digs)}
    end;      
  end;  
*}

ML{* (* IntInf.sml(42) *)
  val quotRem: int*int->int*int = RunCall.run_call2C2 POLY_SYS_quotrem
*}

低级别分工

高级Integer.div_mod in integer.ML,上面的翻译没有使用:

(* THE FUNCTION WHICH TRANSLATES A LIST OF DIGITS/STRINGS TO A ML INTEGER *)
ML{* 
  Library.read_radix_int;     (* int -> string list -> int * string list *)
  Library.read_radix_int 10 ["1","5"];  (* (15, []): int * string list.*)
  Library.read_radix_int 10 ["1","5"] = (15, []);
*}

ML{* (* library.ML(670)  *)
  fun read_radix_int radix cs =
    let
      val zero = ord "0";
      val limit = zero + radix;
      fun scan (num, []) = (num, [])
        | scan (num, c :: cs) =
            if zero <= ord c andalso ord c < limit then
              scan (radix * num + (ord c - zero), cs)
            else (num, c :: cs);
    in scan (0, cs) end;
*}

在Isabelle2013-2 \ contrib \ polyml-5.5.1-1 \ src \ basis \ IntInf.sml中,可以将较高级别 fun div_mod x y = IntInf.divMod (x, y); 与较低级别divMod进行比较:< / p>

quotRem

ML{* (* IntInf.sml(42) *) val quotRem: int*int->int*int = RunCall.run_call2C2 POLY_SYS_quotrem (* This should really be defined in terms of quotRem. *) fun divMod(i, j) = (i div j, i mod j) *} 的低级操作显然是在汇编语言级别完成的:

quotRem

这些不同形式的 ML{* (* RuntimeCalls.ML(83) *) val POLY_SYS_quotrem = 104 (* DCJM 05/03/10 *) *} (* x86asm.asm(1660) quotrem_really_long: MOVL Reax,Redi CALLMACRO CALL_IO POLY_SYS_quotrem CALLMACRO RegMask quotrem,(M_Reax OR M_Redi OR M_Redx OR Mask_all) *) div对我很重要。

我认为如果可能的话,应该避免使用moddiv,但是如果划分是不可避免的,我认为绑定mod将是可行的方法。< / p>