明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
查看: 405|回复: 2

[源码] 用辗转相除法求自然数e关于模φ的逆

[复制链接]
发表于 2020-2-23 15:11 | 显示全部楼层 |阅读模式
本帖最后由 ashleytgg 于 2020-2-23 15:32 编辑

欧几里得的辗转相除除法是数论中最基本的定律,但我用lisp 把它结合起来,觉得还是很有点乐趣,所有和大家分享下。
  1. ;;用辗转相除法 求两个自然数的 最大公约数  相对应的lsp 函数为 (gcd a b)  


  2. ;; output_mode 为输出方式,默认状态下输出 最大公约数,否则输出 辗转相除法的点对
  3. (defun seek_greatest_common_divisor
  4.        (a b output_mode / temp r group_pair)
  5.   (if (< a b)
  6.     (setq temp a
  7.     a b
  8.     b temp

  9.     )
  10.   )
  11.   (setq  group_pair
  12.    (list (list a b))
  13.   )
  14.   (while (/= (setq r (rem a b))
  15.        0
  16.    )
  17.     (setq a b
  18.     b r
  19.     group_pair
  20.      (cons (list a b) group_pair)
  21.     )
  22.   )
  23.   (setq group_pair (reverse group_pair))
  24.   (if output_mode
  25.     group_pair
  26.     b
  27.   )
  28. )
  29. ;;   ( seek_greatest_common_divisor   (*  2 3 5 7)  (* 137 7 59 3 ) t )  
  30. ;;   (gcd (*  2 3 5 7)  (* 137 7 59 3 )   )
  31. ;;  ( seek_greatest_common_divisor  3120 17 t )  

  32. ;; 定义一个二元列表(a b) 乘以一个数 (a b)* c = (ab bc)
  33. (defun [a_b]XC (lst c /)
  34.   (list  (* (car lst) c)
  35.   (* (cadr lst) c)
  36.   )
  37. )
  38. ;;定义一个二元列表相加的函数
  39. (defun [a_b]+[c_d]+[e_f] (lst1 lst2 lst3 / lst)
  40.   (mapcar '+ lst1 lst2 lst3)
  41. )



  42. ;; 求 一次整数方程 ed + kφ= 1  的解 , 其中 e 和 φ 是 互素的  
  43. ;; (setq e 79  φ_module 3120 )
  44. (defun seek_inverse_of_module
  45.             (e φ_module / group lst i x y d)
  46.   (if (or (null e)
  47.     (null φ_module)
  48.       )
  49.     (setq e 17
  50.     φ_module 3120
  51.     )
  52.   )
  53.   ;; 把e 限制在 模φ_module 的最小剩余系内  
  54.   (setq e (rem e φ_module))
  55.   ;; 当 (e φ_module) 是互质数时,程序进入计算,否则ed ≡1 (mode φ_module ) 无解
  56.   (if (and (= (gcd e φ_module) 1)
  57.      (/= e 1)
  58.       )
  59.     (progn
  60.       (setq
  61.   ;; 用辗转相除法 求出 3120  17 的点对group ( (3120 17) (17 9) (9 8) (8 1) )
  62.   group
  63.         (seek_greatest_common_divisor e φ_module t)
  64.   group (reverse group)
  65.   ;; 当group((8 1) (9 8) (17 9) (3120 17))  第一一个元素 8能够整除1 时,去掉这个元素,为了程序计算需要
  66.   group (cdr group)
  67.   ;; 把group((9 8) (17 9) (3120 17))  中每个元素比如 3120/17 的商183加入到 (3120 17 183)
  68.   group
  69.         (mapcar '(lambda (lst / dividend divisor)
  70.        (mapcar 'set '(dividend divisor) lst)
  71.        (list dividend divisor (/ dividend divisor))
  72.            )
  73.           group
  74.         )
  75.       )
  76.       ;|  程序说明:
  77.     用辗转相除法求方程 ed + kφ= 1 的e 关于模 φ 的逆  
  78.    group 结构为 ( (9 8 1) (17 9 1) (3120 17 183)  )   
  79.         9= 3120 + 17*(-183)
  80.          8= 17 + 9* (-1)  
  81. 答案1:  1 = 9*(1) + 8* (-1)    ==> 1 = 9 + [17 + 9*(-1)] * (-1)        
  82.                     答案2:  ==> 1= 17* (-1) + 9* 2                  
  83.                            ==> 1= 17* (-1) + [3120 + 17*(-183)]*2  
  84.                     答案3: ==> 1= 3120*2  +  17* (-367)            
  85.   答案1 、答案2、答案3 的解系数为: ( (1 -1) (-1 2) (2 -367) )
  86.   |;
  87.       (setq i 0)
  88.       (mapcar '(lambda (lst / dividend divisor quotient lst_2)
  89.      (mapcar 'set '(dividend divisor quotient) lst)
  90.      ;; x y dividend divisor 之间的关系( dividend divisor)* (x y)T =1  
  91.      (if (= i 0)
  92.        ;; lst 为 group 的初始项时
  93.        (setq x 1
  94.        y (* -1 quotient)
  95.        )
  96.        (progn
  97.          (setq lst_2 ([a_b]+[c_d]+[e_f]
  98.            ([a_b]XC (list 0 divisor) x)
  99.            ([a_b]XC (list dividend 0) y)
  100.            ([a_b]XC (list 0 (* -1 divisor quotient))
  101.               y
  102.            )
  103.          )
  104.          x   (/ (car lst_2) dividend)
  105.          y   (/ (cadr lst_2) divisor)
  106.          )
  107.        )
  108.      )
  109.      ;| 当lst 不是group 中的 第一项时  
  110.          (  dividend divisor)* (x y)T ==(dividend_前 (dividend-divisor*商) )(x y)T      
  111.             而 divisor_前 前一项的被除数 就等于当前项的 除数 divisor  
  112.             |;
  113.      (setq i (1+ i))
  114.      (list x y)
  115.          )
  116.         group
  117.       )
  118.       ;;方程 ey ≡1 (mode φ_module ) 的e 关于模 φ 的逆 为 y
  119.       (cond
  120.   ((< (rem y φ_module) 0)
  121.    (+ (rem y φ_module) φ_module)
  122.   )
  123.   ((> (rem y φ_module) φ_module)
  124.    (- (rem y φ_module) φ_module)
  125.   )
  126.   (t
  127.    (rem y φ_module)
  128.   )
  129.       )
  130.     )
  131.     ;;当 (e φ_module) 不是互质数时 或 e =1 时
  132.     (progn
  133.       (cond
  134.   ((= e 1)
  135.    (setq y 1)
  136.   )
  137.   (t
  138.    (princ "您说输入的参数无解!\n")
  139.   )
  140.       )
  141.     )
  142.   )
  143.   ;; (if  (and (= (gcd e φ_module) 1)   函数结束
  144. )
  145. ;|  (defun seek_inverse_of_module  函数结束 )   (defun seek_inverse_of_module  函数结束 )   (defun seek_inverse_of_module  函数结束 )
  146.       (setq φ_module 3120)  (setq φ_module 11018)  
  147.       ;; 验证程序的正确性  
  148.       (mapcar '(lambda (e)
  149.      (setq
  150.        d (seek_inverse_of_module e φ_module)
  151.      )
  152.      (if (numberp d)
  153.        (cond
  154.          ((< (rem (* e d) φ_module) 0)
  155.           (+ (rem (* e d) φ_module) φ_module)
  156.          )
  157.          ((> (rem (* e d) 3120) φ_module)
  158.           (- (rem (* e d) 3120) φ_module)
  159.          )
  160.          (t
  161.           (rem (* e d) φ_module)
  162.          )
  163.        )
  164.        "无解"
  165.      )
  166.          )
  167.         (list 4    13  17    61    83    97  113   151
  168.         211    281  379   509   683    911  1217  1627
  169.         2179  2909  3881  6907  9209
  170.        )
  171.       )
  172.    (seek_inverse_of_module 1  3120 )   
  173. |;



  174. (defun C:辗转相除法
  175.         (/      dcl_file     dcl_id
  176.          key    lst_         keys
  177.          φ_module    group_residual_system
  178.          i      group
  179.         )
  180.   ;; 定义一个用数组group_residual_system 填充列表框 "list_φ" 的函数
  181.   (defun add_list_list_φ (group_residual_system / i)
  182.     (start_list "list_φ")
  183.     (setq i 1)
  184.     (mapcar '(lambda (x)
  185.          (add_list (strcat "第" (itoa i) "个元素:" (itoa x)))
  186.          (setq i (1+ i))
  187.        )
  188.       group_residual_system
  189.     )
  190.     (end_list)
  191.   )
  192.   ;;   ( add_list_list_φ  group_residual_system )   

  193.   ;; 定义一个函数求模φ_module 的最简剩余系
  194.   (defun create_residual_system  (φ_module / group_residual_system i)

  195.     (setq i 1
  196.     group_residual_system
  197.      nil
  198.     )
  199.     (repeat (1- φ_module)
  200.       (if (= (gcd i φ_module) 1)
  201.   (setq group_residual_system
  202.          (cons i group_residual_system)
  203.   )
  204.       )
  205.       (setq i (1+ i))
  206.     )
  207.     (reverse group_residual_system)
  208.   )
  209.   ;; (setq group_residual_system (create_residual_system  φ_module  ))   

  210.   (vl-load-com)
  211.   ;; 创建一个dcl临时文件,并加载该文件,返回关键字 dcl_id  
  212.   (setq dcl_id (create_tmp_dcl))
  213.   (new_dialog "tang_dcl" dcl_id)
  214.   (setq  φ_module        (read (get_tile "φ"))
  215.   ;; 求模φ_module 的 最简剩余系
  216.   group_residual_system (create_residual_system φ_module)
  217.   )
  218.   ;; 对列表框"list_φ" 进行填充
  219.   (add_list_list_φ group_residual_system)
  220.   ;; 对txt 控件 "tang1" 进行赋值  
  221.   (set_tile "tang1"
  222.       (strcat "模" (itoa φ_module) "的最简剩余系:")
  223.   )
  224.   (set_tile "tang2"
  225.       (strcat "共" (itoa (length group_residual_system)) "个元素")
  226.   )
  227.   ;;定义各控件 的动作函数  
  228.   (foreach key '("list_φ" "cacuate" "φ" "e")
  229.     (action_tile key "(Action_辗转相除法  $key $value )")
  230.   )
  231.   (defun Action_辗转相除法 (key value / lst)
  232.     (cond
  233.       ((= key "list_φ")
  234.        (setq e (nth (read value) group_residual_system))
  235.        (mapcar '(lambda  (x value)
  236.       (set_tile x value)
  237.     )
  238.          (list "e" "d")
  239.          (list (itoa e) "")
  240.        )
  241.       )
  242.       ;; 计算按钮的动作函数 求  ed ≡1 (mode φ_module ) 的解 d
  243.       ((= key "cacuate")
  244.        (setq e         (get_tile "e")
  245.        φ_module (read (get_tile "φ"))
  246.        )
  247.        (if (and
  248.        ;; (read value) 是数值
  249.        (numberp (VL-CATCH-ALL-APPLY
  250.       'read
  251.       (list e)
  252.           )
  253.        )
  254.        ;; (read value) 是整数
  255.        (= (type (setq e (read e))) 'int)
  256.        ;; (read value) 是>1 的整数
  257.        (> e 0)
  258.      )
  259.    (progn
  260.      (setq
  261.        d (seek_inverse_of_module e φ_module)
  262.      )
  263.      (if (numberp d)
  264.        (set_tile "d" (itoa d))
  265.        ;; 当 ed ≡1 (mode φ_module )无解时
  266.        (set_tile "d" "无解")
  267.      )
  268.    )
  269.    (progn
  270.      (alert "你的输入的e有误,请重新输入!")
  271.      (mode_tile "e" 2)
  272.    )
  273.        )
  274.        ;;if  (and  (numberp (VL-CATCH-ALL-APPLY   
  275.       )
  276.       ;;  编辑框"φ" 的动作函数
  277.       ((= key "φ")
  278.        (if (and
  279.        ;; (read value) 是数值
  280.        (numberp (VL-CATCH-ALL-APPLY
  281.       'read
  282.       (list value)
  283.           )
  284.        )
  285.        ;; (read value) 是整数
  286.        (= (type (read value)) 'int)
  287.        ;; (read value) 是>1 的整数
  288.        (> (read value) 1)
  289.      )
  290.    ;; 当value 是 整数时  
  291.    (progn
  292.      ;; 对txt 控件 "tang1" 进行赋值  
  293.      (set_tile "tang1"
  294.          (strcat "模" value "的最简剩余系:")
  295.      )
  296.      (setq
  297.        group_residual_system
  298.         (create_residual_system (read value))
  299.      )
  300.      ;; 对列表框"list_φ" 进行填充 ,当group_residual_system 的个数大于1万个时,只填充前1万项
  301.      (if (< (length group_residual_system) 10000)
  302.        (add_list_list_φ group_residual_system)
  303.        (progn
  304.          (setq group nil)
  305.          (repeat 10000
  306.      (setq group (cons 0 group))
  307.          )
  308.          ;; 取group_residual_system 中的前1万项
  309.          (add_list_list_φ
  310.      (mapcar '+ group_residual_system group)
  311.          )
  312.          (set_tile
  313.      "tang3"
  314.      "只显示前1万项!"
  315.          )
  316.        )
  317.        ;;(if (< (length group_residual_system) 10000)
  318.      )
  319.      ;; (if (> (length group_residual_system) 10000)
  320.      (set_tile
  321.        "tang2"
  322.        (strcat "共"
  323.          (itoa (length group_residual_system))
  324.          "个元素"
  325.        )
  326.      )
  327.    )
  328.    ;; progn 函数结束
  329.    (progn
  330.      ;; 当value 不是整数,或者是等于1 时
  331.      (alert "你的输入有误,请重新输入!")
  332.      (mode_tile key 2)
  333.    )
  334.        )
  335.        ;;if  (and  (numberp (VL-CATCH-ALL-APPLY
  336.        (set_tile "d" "")
  337.       )
  338.       ;;  编辑框"φ" 的动作函数 结束
  339.       ((= key "e")
  340.        (set_tile "d" "")
  341.       )
  342.     )
  343.     ;;cond 函数结束

  344.   )
  345.   ;; (defun Action_辗转相除法 (key value
  346.   (setq Dialog_Return (start_dialog))
  347.   (unload_dialog dcl_id)

  348. )
  349. ;; (defun C:辗转相除法  函数结束  





  350. ;; 创建一个临时dcl 文件 ,并打开它,返回关键字dcl_id  
  351. (defun create_tmp_dcl (/ f TMPDCL dcl_id)
  352.   (setq  group_str
  353.    '(""
  354.      "tang_dcl:dialog"
  355.      "{"
  356.      "    label = \"用欧几里得辗转相除法解同余方程:ed ≡1 (mode φ) \" ;"
  357.      "    spacer;"
  358.      "    :boxed_row"
  359.      "    {"
  360.      "        alignment = centered ;"
  361.      "        children_fixed_width = true ;"
  362.      "        fixed_height = true ;"
  363.      "        fixed_width = true ;"
  364.      "        :column"
  365.      "        {"
  366.      "            :text"
  367.      "            {"
  368.      "                label = \"模φ的最简剩余系:\" ;"
  369.      "                key =\"tang1\" ;"
  370.      "            }"
  371.      "            :text"
  372.      "            {"
  373.      "                label = \"共8个元素\" ;"
  374.      "                key =\"tang2\" ;"
  375.      "            }"
  376.      "            :text"
  377.      "            {"
  378.      "                label = \"\" ;"
  379.      "                key =\"tang3\" ;"
  380.      "            }"
  381.      "            :list_box"
  382.      "            {"
  383.      "                fixed_height = false ;"
  384.      "                fixed_width = true ;"
  385.      "                is_tab_stop = true ;"
  386.      "                key = \"list_φ\" ;"
  387.      "                width = 20 ;"
  388.      "            }"
  389.      "        }"
  390.      "        :column"
  391.      "        {"
  392.      "            fixed_height = true ;"
  393.      "            :edit_box"
  394.      "            {"
  395.      "                edit_width = 8 ;"
  396.      "                is_enabled = true ;"
  397.      "                key = \"e\" ;"
  398.      "                label = \"方程ed ≡1 (mod φ)的e\" ;"
  399.      "                value=\"17\" ;"
  400.      "            }"
  401.      "            :edit_box"
  402.      "            {"
  403.      "                edit_width = 8 ;"
  404.      "                key = \"φ\" ;"
  405.      "                label = \"方程ed ≡1 (mod φ)的φ\" ;"
  406.      "                value=\"3120\" ;"
  407.      "            }"
  408.      "            :row"
  409.      "            {"
  410.      "                :button"
  411.      "                {"
  412.      "                    key = \"cacuate\" ;"
  413.      "                    fixed_width = true ;"
  414.      "                    label = \"计算e对模φ的逆: d\" ;"
  415.      "                    width = 6 ;"
  416.      "                }"
  417.      "                :edit_box"
  418.      "                {"
  419.      "                    edit_width = 8 ;"
  420.      "                    key = \"d\" ;"
  421.      "                    label = \"\" ;"
  422.      "                }"
  423.      "            }"
  424.      "        }"
  425.      "    }"
  426.      "    :row"
  427.      "    {"
  428.      "        alignment = centered ;"
  429.      "        children_fixed_width = true ;"
  430.      "        fixed_width = true ;"
  431.      "        spacer_1;"
  432.      "        :button"
  433.      "        {"
  434.      "            is_cancel = true ;"
  435.      "            key = \"cancel\" ;"
  436.      "            label = \"取消\" ;"
  437.      "            width = 15 ;"
  438.      "        }"
  439.      "    }"
  440.      "}"
  441.     )
  442.   )
  443.   (SETQ TMPDCL (VL-FILENAME-MKTEMP "tmp" "" ".dcl"))
  444.   (setq f (open tmpdcl "w"))
  445.   (foreach str group_str
  446.     (write-line str f)
  447.   )
  448.   (close f)
  449.   (setq dcl_id (load_dialog TMPDCL))
  450.   (vl-file-delete TMPDCL)
  451.   dcl_id
  452. )
  453. ;;( create_tmp_dcl )  

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?注册

x
"觉得好,就打赏"
还没有人打赏,支持一下
发表于 2020-2-23 22:26 | 显示全部楼层
好好学习下~~~
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-4-28 19:37 , Processed in 0.935163 second(s), 27 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表