明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
楼主: cabinsummer

[风之影][Lisp大挑战第一季]圆周率

    [复制链接]
发表于 2011-11-2 11:18:52 | 显示全部楼层
只有仰望的份了
发表于 2011-11-2 16:42:04 | 显示全部楼层
仰望啊!唉!脖子都痛了!
 楼主| 发表于 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位

发表于 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,汗

重在参与

点评

莱布尼茨公式,不错不错!  发表于 2011-11-3 21:54
所有数据类型都是整数,算出来的当然是整数. 楼主这个题目很难的,重点不在数值计算,在于怎样获得每一位数字。  发表于 2011-11-3 16:52
发表于 2011-11-3 17:13:16 | 显示全部楼层
仰望中……
 楼主| 发表于 2011-11-3 19:43:47 | 显示全部楼层
mmh1 发表于 2011-11-3 16:32
(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
效果出来了,但收敛速度太慢,而且精度也不高
鼓励继续
发表于 2011-11-3 20:13:10 | 显示全部楼层
数学太神奇了~~
 楼主| 发表于 2011-11-3 21:05:26 | 显示全部楼层
本帖最后由 cabinsummer 于 2011-11-13 07:13 编辑

继续提供思路。

定义有d个数值且为0的表
  1. (defun ZeroList(d / a)
  2.   (repeat d
  3.     (setq a (append a (list 0)))
  4.   )
  5.   a
  6. )


两表相加
  1. (defun AddList(xlist ylist / a b c)
  2.   (setq a (mapcar '+ xlist ylist))
  3.   (setq b (append (cdr (mapcar '(lambda(x)(/ x 1000000)) a))(list 0)))
  4.   (setq c (mapcar '(lambda(x)(rem x 1000000)) a))
  5.   (mapcar '+ b c)
  6. )


两表相减
  1. (defun MinusList(xlist ylist / n a tt tag)
  2.   (setq n (1- (length xlist)) a nil tag 0)
  3.   (repeat (length xlist)
  4.     (setq tt (- (nth n xlist)(nth n ylist) tag))
  5.     (if (< tt 0)
  6.       (progn
  7. (setq tt (+ tt 1000000))
  8. (setq tag 1)
  9.       )
  10.       (setq tag 0)
  11.     )
  12.     (setq a (cons tt a))
  13.     (setq n (1- n))
  14.   )
  15.   a
  16. )


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


表除以常数d并整理
  1. (defun Divide(xlist d / n v r g a)
  2.   (setq n 0 r 0 a nil)
  3.   (repeat (length xlist)
  4.     (setq v (+ (nth n xlist) (* r 1000000)))
  5.     (setq g (/ v d))
  6.     (setq r (rem v d))
  7.     (setq a (append a (list g)))
  8.     (setq n (1+ n))
  9.   )
  10.   a
  11. )


精度d位u倒数并整理
  1. (defun ReverseNumber(u d / n v r g a)
  2.   (setq xlist (zerolist d))
  3.   (setq n 0 r 1)
  4.   (repeat d
  5.     (setq v (+ (nth n xlist) (* r 1000000)))
  6.     (setq g (/ v u))
  7.     (setq r (rem v u))
  8.     (setq a (append a (list g)))
  9.     (setq n (1+ n))
  10.   )
  11.   a
  12. )


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



发表于 2011-11-4 16:02:40 | 显示全部楼层
顶起来,学习的好材料,不过太难了,我先学点简单的吧!!
 楼主| 发表于 2011-11-4 19:25:30 | 显示全部楼层
本帖最后由 cabinsummer 于 2011-11-4 19:26 编辑

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





本帖子中包含更多资源

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

x
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-11-26 15:44 , Processed in 0.177719 second(s), 23 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

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