免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
楼主: 星条旗
打印 上一主题 下一主题

[学习共享] 来写几段天书式的dc程序 [复制链接]

论坛徽章:
0
11 [报告]
发表于 2012-12-02 09:09 |只看该作者
hbmhalley 发表于 2012-12-01 22:07
回复 7# 星条旗


谢谢, 学习了!

计算余弦函数值
  1. dc -e '100k ? s~ 1[ s! l~ 2 l! * ^  2 l! * [q]s.[d1=.d1-l_x*]ds_x / 0 1 - l! ^ * l!1+ l!20>w]swlwxs= 1 z [s@ + l@ 1- d1<<]s<l<xs= p'
复制代码

论坛徽章:
0
12 [报告]
发表于 2012-12-02 09:10 |只看该作者
ecjtubaowp 发表于 2012-12-01 22:57
不实用,感觉。


dc语言确实很晦涩,但是重要的是语法的模型结构,这才是需要学习的地方。

论坛徽章:
0
13 [报告]
发表于 2012-12-02 09:12 |只看该作者
求输入两个数的 最小公倍数,
  1. dc -e '?[s!s_l_l![dS$rL$%d0<$]ds$x+s#l!l_*l#/]s.l.xp'
复制代码
  1. dc -e '?[s!s_l_l![dS$rL$%d0<$]ds$x+s#l!l_*l#/]s.l.xp'
  2. 9 12
  3. 36
复制代码

论坛徽章:
0
14 [报告]
发表于 2012-12-02 09:23 |只看该作者
  1. dc -e '1 [s~ l~ s. 1 s_ [[f]s$l$x l_1+s_ l_l~>+]s? [l~d * l_d * + 2 l~ l_ ** l~d * l_d* - l_l~>?]s+l+x c l~1+ d0<u]suluxf' | sed -n '1~3N;s/\n/ /;N;s/\n/ /;p'
复制代码
列出所有3 4 5之类的勾股数组,用sed格式化输出结果。

论坛徽章:
0
15 [报告]
发表于 2012-12-02 09:29 |只看该作者
找出数组中的最大值。
  1. echo '3 1 0 4.3 1.2 3.5 3.2 2  z [s@ [r so l@ 1-d1!=j]sy [so l@ 1- d1!=j]sh [st d lt r Lt =h]s!l!x [st d lt r Lt >y]selex [so d lo r Lo <h]sulux ]sjljxs# f' |dc
  2. 4.3
复制代码
awk在0和1之间随机取值 ,用dc找出其中最大的。
  1. awk 'BEGIN{ORS="\t";while(k++<100){print rand()} print "z [s@ [r so l@ 1-d1!=j]sy [so l@ 1- d1!=j]sh [st d lt r Lt =h]s!l!x [st d lt r Lt >y]selex [so d lo r Lo <h]sulux ]sjljxs# f"}' | dc
复制代码

论坛徽章:
0
16 [报告]
发表于 2012-12-02 09:56 |只看该作者
本帖最后由 星条旗 于 2012-12-02 09:58 编辑

一般来说,做类似于for的循环的流程可以有三种写法,以 1+2+3+4+。。。+10 为例
1.
  1. dc -e '10[d1-d1<R+]d sR x p'
复制代码
[d1-d1<R+]d sR x 的意思是先将[d1-d1<R+]压进主栈栈顶,d命令再复制字符串[d1-d1<R+]压入到主栈栈顶,这时主栈栈顶头两个值都是[d1-d1<R+] ,sR将主栈栈顶的值[d1-d1<R+]弹出并压入寄存器R,这时主栈栈顶还剩一个 [d1-d1<R+],x命令最后将主栈栈顶的[d1-d1<R+]弹出,并解释执行d1-d1<R+。

2.
  1. dc -e '10[d1-d1<R+]sRlRx p'
复制代码
[d1-d1<R+]sRlRx的意思是先将[d1-d1<R+]压进主栈栈顶,sR将主栈栈顶的值[d1-d1<R+]弹出并压入寄存器R,lR将寄存器R的值[d1-d1<R+]压入到主栈此时寄存器R顶部值还是[d1-d1<R+],x命令最后将主栈栈顶的[d1-d1<R+]弹出,并解释执行d1-d1<R+ 。

3.
  1. dc -e '10[q]sQ[d1=Q  d1-lRx+] dsRx p'
复制代码
首先在[d1=Q  d1-lRx+]中,中的d1=Q  意思是当主栈栈顶头两个值相等时,会跳转到寄存器Q ,并执行Q中为退出循环体的命令。
dsRx与 情况 1相同,lRx的意思与 情况2相同。






论坛徽章:
0
17 [报告]
发表于 2012-12-02 10:09 |只看该作者
本帖最后由 星条旗 于 2012-12-02 10:17 编辑

一般对这种类似于x86汇编指令式的栈操作式语言不了解的初学者来说要想读懂dc程序,必须对主栈和所有寄存器的变化情况进行跟踪。
由于喜欢用dc写程序的人都喜欢炫耀一下自己天书般难懂的程序,所以他们在寄存器名称的选取上经常使用!~_@%¥&{}:">`+=-
等符号,而不是使用a b c d ...这些字母。所以,这从客观上更加重了dc程序的难懂性和神秘性。
比如,把我16楼第一个程序中的寄存器R
  1. dc -e '10[d1-d1<R+]d sR x p'
复制代码
改写成+号
  1. dc -e '10[d1-d1<++]ds+xp'
复制代码
是不是变的有些难懂了?

论坛徽章:
0
18 [报告]
发表于 2012-12-02 11:23 |只看该作者
hbmhalley 童鞋在文章中有过对if流程的介绍,额再举个例子锦上添花一下。

http://bbs.chinaunix.net/thread-3714461-1-1.html

在dc中,对于if 条件的表示可以采用条件式跳转的方法。

例如,要编写一个输入 1 打印 one  ,输入 2 打印 two   ,输入 3 打印 three

的dc程序。

额可以先把三种打印的结果放置到三个寄存器T,R, Q中。

然后执行条件匹配命令。
  1. dc -e ' ? sI           # 将输入读进寄存器I

  2. [[one] p q ] sT     # 执行 if主体 ,如果输入1 执行寄存器T的命令,并退出

  3. [[two] p q ] sR     # 执行 if主体 ,如果输入2 执行寄存器R的命令,并退出

  4. [[three] p q ]sQ   # 执行 if主体 ,如果输入3 执行寄存器Q的命令,并退出

  5. [lI  d1=T  d2=R  d3=Q] sE lE x  #执行 if 条件的判定 ,判断输入情况

  6. LIs& LTs& LRs& LQs& LEs&            # 将垃圾回收到寄存器&

  7. '

  8. 2

  9. two
复制代码
但是由于dc程序中没有完整的提供 “非 与 或” 等逻辑判断操作符,所以在编写较为复杂的判断循环dc程序时需要更多经验性技巧。

论坛徽章:
0
19 [报告]
发表于 2012-12-02 14:22 |只看该作者
下面对这个晦涩的求质数的dc程序进行解读:
  1. echo '2p3p[dl!d2+s!%0=@l!l^!<#]s#[s/0ds^]s@[p]s&[ddvs^3s!l#x0<&2+l.x]ds.x'|dc
复制代码
首先要说明的是:
1.作者用"!# @ ./ & ^"这七个字符作为寄存器的名称,使此段程序更具迷惑性。为了易于解读额将
"!# @ ./ & ^"
分别改为“A B C D E F G”
2。
[s/0ds^]s@中的ds^是作者为了让程序更具有迷惑性而加上的,并不具有实际作用。在下面的解读中额会将
[s/0ds^]s@变为[sE 0 ]sD

把符号从新改写过的程序如下:
  1. echo '2p3p[dlAd2+sA%0=ClAlG!<B]sB[sE0dsG]sC[p]sF[ddvsG3sAlBx0<F2+lDx]dsDx' | dc
复制代码
另外,关于质数算法方面该程序用的是最普通质数判别方法。

即: 检查一个正整数N是否为素数,将该数N用小于等于N的平方根的所有奇数去试除,若均无法整除,则N为素数。

由于所有大于2的素数都是奇数,所以此dc程序只是对奇数进行检查。

  1. echo '2p3p                                         #  2 3 进入主栈

  2. [d lA d2+sA %0=C lA lG!<B] sB          #   素数循环判定模块,试除所有小于等于N的平方根的数,如果能除尽则判定失败则将0作为失败标志压入主栈栈顶用于主程序判断。

  3. [sE 0] sC                                           #  如果判定失败将主栈栈顶弹出,并将失败标志0压入主栈栈顶。

  4. [p]sF                                                #  如果成功则打印主栈栈顶

  5. [d dvsG 3sA lBx 0<F 2+ lDx ] dsD x    #  此处为主程序段,在lBx对素数检验完成后,检查主栈栈顶标志,如果不是0则表示素性判定成功,运行寄存器F打印程序,如果失败则检验下一个

  6. ' | dc
复制代码

招聘 : 项目经理
论坛徽章:
0
20 [报告]
发表于 2012-12-02 14:30 |只看该作者
活跃头脑, 开阔视野, 楼主加油
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP