先举一个例子:
多项式乘法:
cts5zsgfyq0.png
- (fft -1 (mapcar 'cmp::MUL (fft 1 '(1 2 3 4 5 6 7 8 0)) (fft 1 '(2 2 1 0 5 5 4 8 0))))
- ==> (2.0 6.0 11.0 16.0 26.0 41.0 60.0 87.0 96.0 103.0 117.0 139.0 116.0 88.0 64.0 0.0)
很完美,和软件计算结果一致。计算精度很高。可以到小数后20位。
再来一个例子:
高精度计算:
譬如高精度乘法:
(gjd "1234567890987654321" "9876543210123456789")
=>"12193263121170553265523548251112635269"
具体代码实现:
- ;;;=============================================================
- ;;; 实数转复数
- ;;;=============================================================
- (defun CMP::R2C (x)
- (if (listp x) x (list x 0))
- )
- ;;;=============================================================
- ;;; 字符串是否只包含数字
- ;;;=============================================================
- (defun isNumber (a)
- (vl-every
- (function (lambda (n) (list a)
- )
- )
- ;;;=============================================================
- ;;; 字符串转数字表
- ;;; 例如:"12312" => '(1 2 3 1 2)
- ;;;=============================================================
- (defun str->num (a / l)
- (setq l (vl-string->list a))
- (if (vl-every (function (lambda (n) ("12193263121170553265523548251112635269"
- ;;;=============================================================
- (defun GJD (a1 a2 / FA LEN LEN1 LEN2 LL N0 N1)
- (if (and (setq a1 (str->num a1)) (setq a2 (str->num a2)))
- (progn
- ;;倒排表(因为十进制数是从高位到低位),并转换为复数
- (setq a1 (mapcar 'CMP::R2C (reverse a1)))
- (setq a2 (mapcar 'CMP::R2C (reverse a2)))
- ;;计算需要补零个数
- (setq len1 (length a1))
- (setq len2 (length a2))
- (setq len (max len1 len2))
- (if (zerop (logand len (1- len)))
- (setq len (* len 2))
- (setq len (expt 2 (+ 2 (fix (/ (log len) (log 2))))))
- )
- ;;补零
- (setq a1 (AppendZero a1 (- len len1)))
- (setq a2 (AppendZero a2 (- len len2)))
- ;;利用FFT把两大数相乘转为多项式乘法
- (setq a1 (RFFT 1 a1))
- (setq a2 (RFFT 1 a2))
- (setq fa (RFFT -1 (mapcar 'cmp::mul a1 a2)))
- ;;小数转整并消除多余的零
- (setq fa (mapcar (function (lambda (x) (fix (+ 0.5 (/ (car x) len))))) fa))
- (setq fa (reverse fa))
- (while (zerop (car fa))
- (setq fa (cdr fa))
- )
- (setq fa (reverse fa))
- ;;进位
- (setq n0 0)
- (foreach n fa
- (setq n1 (+ n n0))
- (setq n0 (/ n1 10))
- (setq ll (cons (rem n1 10) ll))
- )
- (if (/= n0 0)
- (setq ll (cons n0 ll))
- )
- ;;转字符串
- (vl-list->string (mapcar (function (lambda (n) (+ n 48))) ll))
- )
- )
- )
当然,在这个位数不多的情况下,没什么优势,当上万或者更大的时候,FFT算法的优势就可以体现出来了。
FFT用于图像处理、数字信号处理、数据采集、噪声分析、字符串匹配、数学计算(譬如积分、卷积、多项式乘法、高精度计算)等等,用途极其广泛。 而有些应用光靠lisp语言无法实现的。在这里不再一一举例,有很多我都不知道,所以读者自行研究。 |