如何在LISP中乘以两个大整数

时间:2012-04-28 21:01:12

标签: lisp common-lisp

给定n位整数和m位整数。如何使用列表,数组或任何其他特定于lisp的数据类型在LISP中将它们相乘?

例如

;

  

一(1)(2)... A(N)

     

b(1)b(2)... b(m)

结果为;

  

R(1)R(2)... R(M + N)

3 个答案:

答案 0 :(得分:6)

Common Lisp本身已经bignums。你为什么不用它们?

你基本上不必特别声明任何东西,它们“神奇地”发生:

 % sbcl
 This is SBCL 1.0.56.0.debian, an implementation of ANSI Common Lisp.

 * (defun fact (n) (if (< n 1) 1 (* n (fact (- n 1)))))
 FACT

 * (fact 50)
 30414093201713378043612608166064768844377641568960512000000000000

所以使用Common Lisp,你基本上不必费心......

附加物

高效的bignum算法是一个非常困难的问题;高效的算法比天真的算法具有更好的复杂性;你可以找到解释它们的困难书籍(基础数学很难)。另请参阅this answer

如果你想要有竞争力的bignum实施,准备好工作几年,并使其成为博士论文。

答案 1 :(得分:4)

一个简单的算法就是模仿手工计算多重复制时所做的事情:

  123 x
  456 =
  ---
  738
 615
492
-----
56088

第一步是通过单个“数字”(例如123 x 6 = 738)实现乘法。

在您完成移位之后当然是微不足道的(只是列表中的滑动元素),因此可以使用您的加法函数完成乘法。

请注意,这不是计算两个大数字乘积的最快方法(例如,请参阅Karatsuba algorithm)。

PS:思考如何用手计算两个大数的乘积也解释了一些“惊人的”结果,如111111111 * 111111111 = 12345678987654321

         111111111 x
         111111111 =
         ---------
         111111111
        111111111
       111111111
      111111111
     111111111
    111111111
   111111111
  111111111
 111111111
 -----------------
 12345678987654321

答案 2 :(得分:3)

(* 1234567890123456789123456789 1234567890123456789123456789)

Big ints是Common Lisp的原生。