对于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,但是如果我看到上面的内容是如何完成的,它可能会告诉我如何做到这一点。
答案 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来搜索事情是如何完成的,其中位移是我想要的结果,尽管这些可能不是我需要的:
我包含了来自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
对我很重要。
我认为如果可能的话,应该避免使用mod
和div
,但是如果划分是不可避免的,我认为绑定mod
将是可行的方法。< / p>