adolfken 发表于 2011-11-2 11:18:52

只有仰望的份了

董堃 发表于 2011-11-2 16:42:04

仰望啊!唉!脖子都痛了!

cabinsummer 发表于 2011-11-3 00:44:54

本帖最后由 cabinsummer 于 2011-11-3 21:31 编辑

先分析一下。32位的电脑整形数范围为-2^31——(2^31-1),即-2147483648到2147483647。超过这个范围的数值计算,必须分段进行。同样精度数值的计算,分段越少,计算次数也越少,因此每段包含的位数要尽可能的多。
以麦钦公式为例,可以考虑八位一组的分段,因九位一组的分段在计算乘法时可能会超出最大整数范围,导致难以察觉的错误。99999999x16=1599999984<2147483647;而999999999x4=3999999996>2147483647。
同样的分析,上述各反正切计算法能达到的最大分段分别如下:
赫顿公式最大分段8位
麦钦公式最大分段8位
维加公式最大分段8位
欧拉-维加公式最大分段8位
克拉森公式最大分段8位
高斯两个公式最大分段分别是8和7位
卢瑟福公式最大分段8位
达泽公式最大分段8位
山克斯公式最大分段7位
斯特姆公式最大分段7位
肖鲁兹公式最大分段8位
布塞卡公式最大分段7位
艾斯克托公式最大分段7位

mmh1 发表于 2011-11-3 16:32:39

本帖最后由 mmh1 于 2011-11-3 16:33 编辑

(setq a 1 s 1 b 1)
(repeat 10
    (setq a (+ a 2))
    (setq b (* b -1))
    (setq s (+ s (* (/ 1 a) b)))
    )
(setq d (* 4 s))
输出结果为4,汗

重在参与

birdsky 发表于 2011-11-3 17:13:16

仰望中……

cabinsummer 发表于 2011-11-3 19:43:47

mmh1 发表于 2011-11-3 16:32 static/image/common/back.gif
(setq a 1 s 1 b 1)
(repeat 10
    (setq a (+ a 2))


如果第一行改为(setq a 1.0 s 1.0 b 1.0)
输出结果为3.23232
如果再将重复次数改为100
输出结果为3.15149
如果再将重复次数改为1000
输出结果为3.14259
如果再将重复次数改为81000
输出结果为3.1416
效果出来了,但收敛速度太慢,而且精度也不高
鼓励继续

logoin 发表于 2011-11-3 20:13:10

数学太神奇了~~

cabinsummer 发表于 2011-11-3 21:05:26

本帖最后由 cabinsummer 于 2011-11-13 07:13 编辑

继续提供思路。

定义有d个数值且为0的表
(defun ZeroList(d / a)
(repeat d
    (setq a (append a (list 0)))
)
a
)

两表相加
(defun AddList(xlist ylist / a b c)
(setq a (mapcar '+ xlist ylist))
(setq b (append (cdr (mapcar '(lambda(x)(/ x 1000000)) a))(list 0)))
(setq c (mapcar '(lambda(x)(rem x 1000000)) a))
(mapcar '+ b c)
)

两表相减
(defun MinusList(xlist ylist / n a tt tag)
(setq n (1- (length xlist)) a nil tag 0)
(repeat (length xlist)
    (setq tt (- (nth n xlist)(nth n ylist) tag))
    (if (< tt 0)
      (progn
(setq tt (+ tt 1000000))
(setq tag 1)
      )
      (setq tag 0)
    )
    (setq a (cons tt a))
    (setq n (1- n))
)
a
)

表乘以常数d并整理
(defun Multi(xlist d / a b c)
(setq a (mapcar '(lambda(x)(* d x)) xlist))
(setq b (append (cdr (mapcar '(lambda(x)(/ x 1000000)) a))(list 0)))
(setq c (mapcar '(lambda(x)(rem x 1000000)) a))
(mapcar '+ b c)
)

表除以常数d并整理
(defun Divide(xlist d / n v r g a)
(setq n 0 r 0 a nil)
(repeat (length xlist)
    (setq v (+ (nth n xlist) (* r 1000000)))
    (setq g (/ v d))
    (setq r (rem v d))
    (setq a (append a (list g)))
    (setq n (1+ n))
)
a
)

精度d位u倒数并整理
(defun ReverseNumber(u d / n v r g a)
(setq xlist (zerolist d))
(setq n 0 r 1)
(repeat d
    (setq v (+ (nth n xlist) (* r 1000000)))
    (setq g (/ v u))
    (setq r (rem v u))
    (setq a (append a (list g)))
    (setq n (1+ n))
)
a
)

表中数值输出为连接的长字符串,注意LISP只能处理4096个以下的字符,如果计算位数过长,必须改用其它输出方式。
(defun ToString(xlist / a b n fn)
(setq a "\npi=" n 0)
(setq fn (open "c:\\pi.txt" "w"))
(princ a fn)
(repeat (1- (length xlist))
    (setq b (itoa (nth n xlist)))
    (setq a (strcat (substr "00000" (strlen b)) b " ") n (1+ n))
    (princ a fn)
)
(close fn)
(princ)
)


hhh454 发表于 2011-11-4 16:02:40

顶起来,学习的好材料,不过太难了,我先学点简单的吧!!

cabinsummer 发表于 2011-11-4 19:25:30

本帖最后由 cabinsummer 于 2011-11-4 19:26 编辑

继续提供思路
反正切函数的级数表达





页: 1 [2] 3 4 5
查看完整版本: [风之影][Lisp大挑战第一季]圆周率