js常用正则表达式实例

匹配中文字符的正则表达式: [\u4e00-\u9fa5] 

匹配双字节字符(包括汉字在内):[^\x00-\xff] 

应用:计算字符串的长度(一个双字节字符长度计2,ASCII字符计1) 

String.prototype.len=function(){return this.replace([^\x00-\xff]/g,"aa").length;} 

匹配空行的正则表达式:\n[\s| ]*\r 

匹配HTML标记的正则表达式:/<(.*)>.*<\/\1>|<(.*) \/>/  

匹配首尾空格的正则表达式:(^\s*)|(\s*$) 

应用:javascript中没有像vbscript那样的trim函数,我们就可以利用这个表达式来实现,如下: 

String.prototype.trim = function() 

return this.replace(/(^\s*)|(\s*$)/g, ""); 

利用正则表达式分解和转换IP地址: 

下面是利用正则表达式匹配IP地址,并将IP地址转换成对应数值的Javascript程序: 

function IP2V(ip) 

re=/(\d+)\.(\d+)\.(\d+)\.(\d+)/g //匹配IP地址的正则表达式 
if(re.test(ip)) 

return RegExp.$1*Math.pow(255,3))+RegExp.$2*Math.pow(255,2))+RegExp.$3*255+RegExp.$4*1 

else 

throw new Error("Not a valid IP address!") 

不过上面的程序如果不用正则表达式,而直接用split函数来分解可能更简单,程序如下: 

var ip="10.100.20.168" 
ip=ip.split(".") 
alert("IP值是:"+(ip[0]*255*255*255+ip[1]*255*255+ip[2]*255+ip[3]*1)) 

匹配Email地址的正则表达式:\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)* 

匹配网址URL的正则表达式:http://([\w-]+\.)+[\w-]+(/[\w- ./ %&=]*)  

利用正则表达式去除字串中重复的字符的算法程序:[注:此程序不正确,原因见本贴回复] 

var s="abacabefgeeii" 
var s1=s.replace(/(.).*\1/g,"$1") 
var re=new RegExp("["+s1+"]","g") 
var s2=s.replace(re,"")  
alert(s1+s2) //结果为:abcefgi 

这个方法对于字符顺序有要求的字符串可能不适用。 

得用正则表达式从URL地址中提取文件名的javascript程序,如下结果为page1 

s="http://www.9499.net/page1.htm" 
s=s.replace(/(.*\/){0,}([^\.]+).*/ig,"$2") 
alert(s) 

利用正则表达式限制网页表单里的文本框输入内容: 


正则表达式限制只能输入中文:onkeyup="value="/value.replace(/["^\u4E00-\u9FA5]
/g,’’)" onbeforepaste="clipboardData.setData(’text’,clipboardData.getData(’text’).replace(/[^\u4E00-\u9FA5]/g,’’))" 

用正则表达式限制只能输入全角字符: onkeyup="value="/value.replace(/["^\uFF00-
\uFFFF]/g,’’)" onbeforepaste="clipboardData.setData(’text’,clipboardData.getData(’text’).replace(/[^\uFF00-\uFFFF]/g,’’))" 

用正则表达式限制只能输入数字:onkeyup="value="/value.replace(/["^\d]
/g,’’) "onbeforepaste="clipboardData.setData(’text’,clipboardData.getData(’text’).replace(/[^\d]/g,’’))" 

用正则表达式限制只能输入数字和英文:onkeyup="value="/value.replace(/[\W]
/g,"’’) "onbeforepaste="clipboardData.setData(’text’,clipboardData.getData(’text’).replace(/[^\d]/g,’’))"

JavaScriptIRR算法

function IRR(cashFlows, estimatedResult) {
    var result = "isNAN";
    if (cashFlows != null && cashFlows.length > 0) {
        // check if business startup costs is not zero:
        if (cashFlows[0] != 0) {
            var noOfCashFlows = cashFlows.length;
            var sumCashFlows = 0;
            // check if at least 1 positive and 1 negative cash flow exists:
            var noOfNegativeCashFlows = 0;
            var noOfPositiveCashFlows = 0;
            for (var i = 0; i < noOfCashFlows; i++) {
                sumCashFlows += cashFlows[i];
                if (cashFlows[i] > 0) {
                    noOfPositiveCashFlows++;
                } else {
                    if (cashFlows[i] < 0) {
                        noOfNegativeCashFlows++;
                    }
                }
            }

            // at least 1 negative and 1 positive cash flow available 
            if (noOfNegativeCashFlows > 0 && noOfPositiveCashFlows > 0) {
                // set estimated result:
                var irrGuess = 0.1; // default: 10%
                if (!isNaN(estimatedResult)) {
                    irrGuess = estimatedResult;
                    if (irrGuess <= 0) {
                        irrGuess = 0.5;
                    }
                }

                // initialize first IRR with estimated result:
                var irr = 0;
                if (sumCashFlows < 0) { // sum of cash flows negative 
                    irr = -irrGuess;
                } else { // sum of cash flows not negative
                    irr = irrGuess;
                }

                // iteration:
                // the smaller the distance, the smaller the interpolation
                // error
                var minDistance = 1e-15;

                // business startup costs
                var cashFlowStart = cashFlows[0];
                var maxIteration = 100;
                var wasHi = false;
                var cashValue = 0;
                for (var i = 0; i <= maxIteration; i++) {
                    // calculate cash value with current irr:
                    cashValue = cashFlowStart; // init with startup costs

                    // for each cash flow
                    for (var j = 1; j < noOfCashFlows; j++) {
                        cashValue += cashFlows[j] / Math.pow(1 + irr, j);
                    }

                    // cash value is nearly zero
                    if (Math.abs(cashValue) < 0.01) {
                        result = irr;
                        break;
                    }

                    // adjust irr for next iteration:
                    // cash value > 0 => next irr > current irr
                    if (cashValue > 0) {
                        if (wasHi) {
                            irrGuess /= 2;
                        }
                        irr += irrGuess;
                        if (wasHi) {
                            irrGuess -= minDistance;
                            wasHi = false;
                        }
                    } else {// cash value < 0 => next irr < current irr
                        irrGuess /= 2;
                        irr -= irrGuess;
                        wasHi = true;
                    }

                    // estimated result too small to continue => end
                    // calculation
                    if (irrGuess <= minDistance) {
                        result = irr;
                        break;
                    }
                }
            }
        }
    }
    return result;
}

 

 

商業性語言?

剛剛又回去看這篇文章,發現作者的回應實在好歡樂呀。

還有 PHP 在 WIKIPEDIA 上被歸類為工業程式語言,並不屬於 script language。

原來如此,程式語言還可以這樣分工業程式語言跟 Scripting Language XD ,作者居然還振振有詞的這樣強調。而且 PHP 居然是工業編程語言而非 Scripting Language,真是大出我的意料之外,我居然沒聽過這樣的分類。

我得先翻翻看工業編程語言的定義,直接看原作者怎麼講的

Java 屬於工業編程語言

程式設計語言,通常簡稱為編程語言,是一組用來定義電腦程式的語法規則。它是一種被標準化的交流技巧,用來向電腦發出指令。一種電腦語言讓程式設計師能夠準確地定義電腦所需要使用的數據,並精確地定義在不同情況下所應當採取的行動。

程式設計語言原本是被設計成專門使用在電腦上的,但它們也可以用來定義演算法或者資料結構。正是因為如此,程式設計師才會試圖使程式代碼更容易閱讀。

原文出處 – Wikipedia – Programming Language

原來如此,原來這就是工業編程語言,我懂了。為了輸人不輸陣,我決定

公告:以後 Ruby 正式成為商業編程語言

商業編程語言,通常簡稱為騙錢語言,是一組用來定義如何快速而有效率瞎掰的語法規則。它是一種被標準化的詐騙技巧,用來向老闆發出虎爛。一種騙錢語言讓程式設計師能夠準確地定義搞定這個案子所需要使用的時間,並精確地定義要謊報多少金錢才能獲得這個專案。

商業編程語言原本是被設計成專門使用在快速開發上面的,但它們也可以用來應用在如何有效率的偷懶或者不被老闆發現的摸魚。正是因為如此,某些素性不良的程式設計師才會試圖使商業性語言更發揚光大,甚至寫一些嘴泡的極點的 Blog來推廣商業性語言。

原文出處 – thgiivepedia – Programming Language

我想說的是

最後作者終於在回應時,出來解釋他這句話

我還是要強調,Java 這類工業程式語言,並不是 script language 可以比較的。因為,拿香蕉跟芭樂比!?你要怎麼比!

我看過組合語言一樣可以做出小畫家,我學生時代也曾經用 Perl 寫一個很簡單的 C Compiler 。只要機器是跑在 tuning machine 的架構下,任何一種程式語言都可以做到其他語言做得到的事情,所以語言當然可以互相比較,有什麼不行?

程式語言就跟真實世界的語言一樣。你用啥語言寫 code 跟你用哪國語言講話一樣,都只是一個選擇而已。我選擇用 Ruby 寫程式,跟我選擇用中文講話一樣,都只是我這樣選擇而已。

Java 背後的專業性,應用範圍,絕對不是 JavaScript 那種 SCRIPT 語言可以比較的」,這句話就跟法國人一直強調的「講法語就是比講英語來的優雅」一樣可笑,充滿著不可思議的傲慢跟無知。我實在不懂用 Java 的人就比較有專業性?用 Scripting Language 就比較沒有專業性?專不專業這跟用什麼語言任何有關係嗎?一個教授的學術地位高低跟他用哪個國家的語言有關係嗎?

程式語言本身並沒有高下之分,程式設計師才有高下之分。

Update:居然我的回應都被刪除了,嘖嘖。

行星的位置计算

许剑伟 莆田十中

[摘要]:行星运动理论有很多种,遗憾的是国内并没有公开发表的系统的行星理论。因此,要想计算行星位置,只能使用国外的或历史上天文学家的天体运动理论进行计算。本文介绍法国天文台的VSOP行星理论,非常适合职业天文学家、业余天文学家甚至普通高中生使用,可得到高精度的行星位置坐标。

[正文]:

随着新课程的推进,我们发现高中物理所涉及的内容越来越广泛,它与现代科学、技术结合得越来越紧密了。比如,现行的高中课程中已涉及半导体技术,然而,不了解半导体技术的教师却不是少数;再比如,高中课程中已讲述了完整的牛顿运动定律、开普勒定律等,大家似乎完全围绕着高考完成教学工作,很少人利用这些定律进行真正的天文计算方面的研究,以至我们的学生根本就不知道这方面的计算是如何进行的,相反,在国外却可找到大量适合中学生掌握的天文计算方法。在这种背景下,中学物理教育工作者有必要更广泛学习、研究现代科学方法,扎实推进新课程改革。本文介绍一种非常容易实现的现代的行星位置计算方法。

    一、选择适当的理论:

目前,人们已掌握多种大行星运动理论,可供我们选择的方法分类如下:

1)直接利用开普勒行星三定律。此类方法属运动学范畴,可获0.01度的黄经精度;

2)拉普拉斯等牛顿的忠实信徒们,利用牛顿定律,结合适当的数学方法得到的行星位置的解析解,此类方法属动力学范畴,称为解析法;

3)运用牛顿定律,直接利用计算机进行数值积分得到超高精度的结果(现代方法)。比较著名的是美国国家航空航天局下属的喷气推进实验室的DE系列星历表。2005年以后的中国紫金山天文台出版的《中国天文年历》就是利用DE405星表推算的。

4)改良前人的解析法解法,使之适合计算机计算(现代方法),此类方法常称为半解析法。这些方法的精度已经非常接近DE系列星历表。

适合中学生及教师的方法是第1种及第4种方法。当然,还须做适当的简化处理,以方便大家理解。本文重点介绍著名的是半解析法VSOP87行星理论,利用它可取得非常高的精度。

二、计算方法:

  1982年,巴黎的P.Bretagnon发表了他的行星理论VSOP82。VSOP是“Variations Seculaires des Orbites Planetaires”的缩写。VSOP82由大星行(水星到海王星)的长长的周期项序列组成。给定一个行星及一个时间,对它的序列取和计算,即可获得密切轨道参数。

    不过VSOP82方法有个不便之处是,当不需要完全精度时,应在何处截断?幸运的是,1987年 Bretagnon 和 Francou 创建了VSOP87行星理论,它提供了直接计算行星日心坐标的周期序列项。也就是说可直接算得:任意时刻的日心黄经L、日心黄纬B、行星到太阳的距离R。

  要注意的是,L是行星的的真黄经,不是轨道经度。如图,x’是行星的真位置,x是平位置(所谓平位置可理解为把行星运动看匀速圆周运动得到的位置),轨道经度是γN + NX’,这两段角度分别在两条不同的轨道上。通过行星的真位置x’垂直画一条黄经线,在黄道上交于x”,那么γx”就是黄经L。虽然VSOP82及VSOP87方法已在国际天文文献上发表,但与其相关的数据是保存在电脑磁盘上的,而且数据量非常大,对于我们来说,并不要求超高精度计算,所以需通过适当变换,截取主要周期项进行计算。笔者通过适当的数学方法,提取了地球的主要周期项数据(详见附表),再通过本文的方法可得到3角秒的精度(-2000至6000年范围内)。这种方法本质上与VSOP87方法是相同的,主要不同之处是做了数据截断处理,计算量非常小。

附表中提供了地球的各个子序列数据表,序列表标号分别为L0,L1,L2…;B0,B1…;R0,R1…。

  计算黄经L使用序列表L0、L1…;计算黄纬使用序列表B0、B1……;计算距离R使用序列表R0、R1……。直得注意的是,黄纬计算相关的子表B0、B1……都是0,所以未列出,地球的日心黄纬的变化范一般不超过2”,所以B表都是0。

    每个表是一组周期项,包含四列数字:

       1)序号:这不是计算所必须的,仅是提供一个参考。

       2)三个数字:分别命名为A、B、C

    设给定的时间JDE是标准的儒略日数,τ是千年数,则τ表达如下:

       τ = (JDE – 2451545.0) / 365250

    则每项(表中各行)的值计算表达式是:

A*cos(B+C*τ)

例如L0表的第9行算式为:

1324*cos(0.7425 + 11506.7698*τ)

附表中B、C的单位是弧度。系数A的单位是:10^-8弧度(适用于黄经和黄纬),10^-8天文单位(适用于距离)。

    按如下算式,可得到行星的Date黄道坐标中的黄经。对L0表各项取和计算,对L1表各项取和计算,其它表类推。接下来用下式得到黄经(单位是弧度):

L = (L0 + L1*τ + L2*τ^2 + L3*τ^3 + L4*τ^4 +L5*τ^5)/10^8 ……1式

    式中τ^2表示τ的2次方,同理τ^3表示τ的3次方。

    用同样的方法继计算B和R。

    注1:可能有些读者对儒略日数不太了解,造成无法计算出τ。那可按如下方法计算τ:对于某时刻,先算出该时刻距2000年1月1日12:00:00的偏离日数D,那么τ= D/365250

    注2:时间表达为力学时,而为是手表时,手表时与地球自转同步,因地球自转速度是不均匀的,并有变慢的趋势,所以手表时也有变慢的趋势。力学时则是非常均匀的(相当于原子时),计算天体位置时均使用力学时。力学时与手表时的转换可用一组经验公式完成,但这已超出本文的内容。

到此为止,我们得到行星在动力学Date平黄道坐标(Bretagnon的VSOP定义的)中的日心黄经L、黄纬B。这个坐标系与标准的FK5坐标系还有细微差别。按如下方法可将L和B转到FK5坐标系中,其中T是世纪数而不是千年数,T=10τ。

先计算:L’ = L – 1°.397*T – 0.00031*T^2

然后计算L和B的修正值:

ΔL = -0″.09033 + 0″.03916*( cos(L’) + sin(L’) )*tan(B)

ΔB = +0″.03916*( cos(L’) – sin(L’) )

仅在十分精确计算时才需进行修正,如果按本文附表提供的序列进行计算,则无需修正。

三、举个例子:

    例31.a ——计算地球的日心Date平黄道坐标, 时间2008年1月1日12时(力学时)

该日期转为儒略日数是:JDE 2454467

这样可得: τ = (2454467 – 2451545)/365250=0.0080000000

计算τ时要保留足够的小数位数,6位小数是远远不够的(除非所需的地球黄经的精度要求很低),注意:τ表达为儒略千年数,所以T误差0.000001相当于0.37日。

  对于地球,附表中,其序列L0有27项(在原VSOP87理论中有很多很多项),L1、L2、L3、L4、L5分别是:14、8、4、3、1项。这些序列取和计算后得到:

L0 = +175 194 034       L3 = 311

L1 = +628 331 778 761    L4 = -119

L2 = +57343            L5 = -1

因此,由1式即可得到地球的日心黄经

        L = 52.01848268弧度 = 1.75300022弧度 = 100°26’ 22”

用同样的方法计算日心黄纬B及距离R。表中没有地球的B0、B1等项,所以B=0。

四、结果的精度

    当我们要取得更高精度时,VSOP87方法收敛得很慢。当我们截取部分序列进行计算时,那么产生的误差的数量级是多少呢 

以下经验公式已经由Bretagnon和Francou给出:

  如果n是保留项数,A是保留项中最小的值,那么当前截断的序列的误差为:

        η*sqrt(n)*A,  式中η小于2,sqrt()是开方函数

    举例来说,让我们来考虑一下地球的日心黄经。在附表中,其L0包含27项,最小系数是156*10^-8弧度。因此,我们可以估计其最大可能误差约为:

2*sqrt(27)*156*10^-8弧度 = 3″.3

  当然序列L1、L2等也有截断误差,用同样的方法进行误差估计,分别为0″.54*τ,0″.1*τ^2等。

五、说明:

以上计算得到的是Date平黄道(当日平黄道)坐标中的行星真位置坐标,而不是视位置坐标,欲获得视位置,还应转换到地心坐标并补上章动修正及光行差修正。

六、参考资料:

1、本文涉及一些天文学术语,可参考《球面天文学》相关著作

2、要想取得VSOP完整的理论及数据表,可利用www.google.cn搜索引,在国外网站上查找。

3、本文仅提供地球数据,要取得其它行星数据可在笔者的网站上下载。这个文件包含了完整的VSOP87数据,以及笔者提截取主要周期项用的程序。

http://www.fjptsz.com/xxjs/xjw/rj/fj/114.rar

打开文件包中的a.htm,并适当修改其中的JavaScript程序,可提取你所需要的各种数据。当然,在提取数据前,你应先进行误差分析,以便提取出理想的数据。

文件包中的Dmer、Dven、Dear、Dmar、Djup、Dsat、Dura、Dnep分别是水星、金星、地球、木星、土星、天王星、海王得的完整的VSOP87序列表

六、附表:地球数据

         行星标识:Earth 表名:L0

         =====================

   1      175347046   0                 0

   2        3341656   4.6692568      6283.07585

   3          34894   4.6261        12566.1517

   4           3497   2.7441         5753.3849

   5           3418   2.8289            3.5231

   6           3136   3.6277        77713.7715

   7           2676   4.4181         7860.4194

   8           2343   6.1352         3930.2097

   9           1324   0.7425        11506.7698

  10           1273   2.0371          529.691

  11           1199   1.1096         1577.3435

  12            990   5.233          5884.927

  13            902   2.045            26.298

  14            857   3.508           398.149

  15            780   1.179          5223.694

  16            753   2.533          5507.553

  17            505   4.583         18849.228

  18            492   4.205           775.523

  19            357   2.92              0.067

  20            317   5.849         11790.629

  21            284   1.899           796.298

  22            271   0.315         10977.079

  23            243   0.345          5486.778

  24            206   4.806          2544.314

  25            205   1.869          5573.143

  26            202   2.458          6069.777

  27            156   0.833           213.299

         行星标识:Earth 表名:L1

         =====================

   1   628331966747   0                 0

   2         206059   2.678235       6283.07585

   3           4303   2.6351        12566.1517

   4            425   1.59              3.523

   5            119   5.796            26.298

   6            109   2.966          1577.344

   7             93   2.59          18849.23

   8             72   1.14            529.69

   9             68   1.87            398.15

  10             67   4.41           5507.55

  11             59   2.89           5223.69

  12             56   2.17            155.42

  13             45   0.4             796.3

  14             36   0.47            775.52

         行星标识:Earth 表名:L2

         =====================

   1          52919   0                 0

   2           8720   1.0721         6283.0758

   3            309   0.867         12566.152

   4             27   0.05              3.52

   5             16   5.19             26.3

   6             16   3.68            155.42

   7             10   0.76          18849.23

   8              9   2.06          77713.77

         行星标识:Earth 表名:L3

         =====================

   1            289   5.844          6283.076

   2             35   0                 0

   3             17   5.49          12566.15

   4              3   5.2             155.42

         行星标识:Earth 表名:L4

         =====================

   1            114   3.142             0

   2              8   4.13           6283.08

   3              1   3.84          12566.15

         行星标识:Earth 表名:L5

         =====================

   1              1   3.14              0

        

        

         行星标识:Earth 表名:R0

         =====================

   1      100013989   0                 0

   2        1670700   3.0984635      6283.07585

   3          13956   3.05525       12566.1517

   4           3084   5.1985        77713.7715

   5           1628   1.1739         5753.3849

   6           1576   2.8469         7860.4194

   7            925   5.453         11506.77

   8            542   4.564          3930.21

   9            472   3.661          5884.927

  10            346   0.964          5507.553

  11            329   5.9            5223.694

  12            307   0.299          5573.143

  13            243   4.273         11790.629

  14            212   5.847          1577.344

  15            186   5.022         10977.079

  16            175   3.012         18849.228

         行星标识:Earth 表名:R1

         =====================

   1         103019   1.10749        6283.07585

   2           1721   1.0644        12566.1517

   3            702   3.142             0

         行星标识:Earth 表名:R2

         =====================

   1           4359   5.7846         6283.0758

   2            124   5.579         12566.152

   3             12   3.14              0

   4              9   3.63          77713.77

         行星标识:Earth 表名:R3

         =====================

   1            145   4.273          6283.076

   2              7   3.92          12566.15

         行星标识:Earth 表名:R4

         =====================

   1              4   2.56           6283.08

        

节气及农历计算程序 VSOP87+ELP/MPP02

http://www.fjptsz.com/xxjs/xjw/rj/113.htm

《天文算法》译著——许剑伟

http://www.fjptsz.com/xxjs/xjw/rj/117/index.htm

寿星万年历

http://www.fjptsz.com/xxjs/xjw/rj/115.htm

javascript之算法优化

正如其他编程语言,代码的写法和算法选用影响javascript的运行时间。与其他编程语言不同的是,javascript可用资源有限,所以优化技术更为重要。

 

一。for,while,do-while循环的性能特性相似,谁也不比谁更快或更慢。除非你要迭代遍历一个属性未知的对象,否则不要使用for-in循环。

 

由于每次迭代操作要搜索实例或原形的属性,for-in 循环每次迭代都要付出更多开销,所以比其他类型

循环慢一些。如果你迭代遍历一个有限的,已知的属性列表,使用其他循环类型更快,可使用如下模式:

 

var props = ["prop1", "prop2"],
var i = 0;
var len = props.length;
while (i < len){
process(object[props[i]]);
i++;
}

 

 

 

二。改善循环性能的最好方法是减少每次迭代中的运算量,并减少循环迭代次数。

 

//slow
for (var i=0; i < items.length; i++){
process(items[i]);
}
//faster
for (var i=0, len=items.length; i < len; i++){
process(items[i]);
}
//fastest
for (var i=items.length; i--; ){
process(items[i]);
}

 达夫设备是一个循环体展开技术,在一次迭代中实际上执行了多次迭代操作。

 

 

var i = items.length % 8;
while(i){
process(items[i--]);
}
i = Math.floor(items.length / 8);
while(i){
process(items[i--]);
process(items[i--]);
process(items[i--]);
process(items[i--]);
process(items[i--]);
process(items[i--]);
process(items[i--]);
process(items[i--]);
}

 

 

三。一般来说,switch总是比if-else更快,但并不总是最好的解决方法。当判断条件较多时,查表法比if-else或者switch更快。

 

//slow
if (value == 0){
return result0;
} else if (value == 1){
return result1;
} else if (value == 2){
return result2;
} else if (value == 3){
return result3;
} else if (value == 4){
return result4;
} else if (value == 5){
return result5;
} else if (value == 6){
return result6;
} else if (value == 7){
return result7;
} else if (value == 8){
return result8;
} else if (value == 9){
return result9;
} else {
return result10;
}

//faster,二分搜索法(此方法适用于需要测试大量数值的情况(相对离散值来说switch 更合适)
if (value < 6){
if (value < 3){
if (value == 0){
return result0;
} else if (value == 1){
return result1;
} else {
return result2;
}
} else {
if (value == 3){
return result3;
} else if (value == 4){
return result4;
} else {
return result5;
}
}
} else {
if (value < 8){
if (value == 6){
return result6;
} else {
return result7;
}
} else {
if (value == 8){
return result8;
} else if (value == 9){
return result9;
} else {
return result10;
}
}
}
//查表法
//define the array of results
var results = [result0, result1, result2, result3, result4, result5, result6, result7, result8, result9, result10]
//return the correct result
return results[value];

 

 

四。浏览器的调用栈尺寸限制了递归算法在javascript中的应用,栈溢出错误导致其他代码也不能正常执行。如果你遇到一个栈溢出错误,将方法修改为一个迭代算法或者使用制表法可以避免重复工作。

 

 

JavaScript 引擎所支持的递归数量与JavaScript 调用栈大小直接相关。只有Internet Explorer 例外,它的

调用栈与可用系统内存相关,其他浏览器有固定的调用栈限制。大多数现代浏览器的调用栈尺寸比老式浏

览器要大(例如Safari 2 调用栈尺寸是100).当你使用了太多的递归,超过最大调用栈尺寸时,浏览器会出错并弹出以下信息:

 

  Internet Explorer: “Stack overflow at line x”

  Firefox: “Too much recursion”

  Safari: “Maximum call stack size exceeded”

  Opera: “Abort (control stack overflow)”

Chrome 是唯一不显示调用栈溢出错误的浏览器。

 

递归模式一:一个函数调用自身

 

function recurse(){
recurse();
}
recurse();

 递归模式二:精巧模式,两个函数互相调用对方

 

 

 

 

function first(){
second();
}
function second(){
first();
}
first();

 

 

任何可以用递归实现的算法都可以用迭代实现:

 

//javascript的合并排序算法
function merge(left, right){
var result = [];
while (left.length > 0 && right.length > 0){
if (left[0] < right[0]){
result.push(left.shift());
} else {
result.push(right.shift());
}
}
return result.concat(left).concat(right);
}
function mergeSort(items){
if (items.length == 1) {
return items;
}
var middle = Math.floor(items.length / 2),
left = items.slice(0, middle),
right = items.slice(middle);
return merge(mergeSort(left), mergeSort(right));
}

//uses the same mergeSort() function from previous example
function mergeSort(items){
if (items.length == 1) {
return items;
}
var work = [];
for (var i=0, len=items.length; i < len; i++){
work.push([items[i]]);
}
work.push([]); //in case of odd number of items
for (var lim=len; lim > 1; lim = (lim+1)/2){
for (var j=0,k=0; k < lim; j++, k+=2){
work[j] = merge(work[k], work[k+1]);
}
work[j] = []; //in case of odd number of items
}
return work[0];
}
虽然迭代版本的合并排序可能比递归版本的慢一些,但它不会像递归版本那样影响调用栈。将递归算法切换为迭代只是避免栈溢出错误的方法之一。

 

 

制表:

制表,通过缓存先前计算结果为后续计算所重复使用,避免了重复工作。这使得制表成为递归算法中有用的技术。

//slow
function factorial(n){
if (n == 0){
return 1;
} else {
return n * factorial(n-1);
}
}
var fact6 = factorial(6);
var fact5 = factorial(5);
var fact4 = factorial(4);

//制表
function memfactorial(n){
if (!memfactorial.cache){
memfactorial.cache = {
"0": 1,
"1": 1
};
}
if (!memfactorial.cache.hasOwnProperty(n)){
memfactorial.cache[n] = n * memfactorial (n-1);
}
return memfactorial.cache[n];
}
var fact6 = memfactorial(6);
var fact5 = memfactorial(5);
var fact4 = memfactorial(4);

 制表过程因每种递归函数而略有不同,但总体上具有相同的模式。为了使一个函数的制表过程更加容易,

你可以定义一个memoize()函数封装基本功能。例如:

function memoize(fundamental, cache){
cache = cache || {};
var shell = function(arg){
if (!cache.hasOwnProperty(arg)){
cache[arg] = fundamental(arg);
}
return cache[arg];
};
return shell;
}
//memoize the factorial function
var memfactorial = memoize(factorial, { "0": 1, "1": 1 });
//call the new function
var fact6 = memfactorial(6);
var fact5 = memfactorial(5);
var fact4 = memfactorial(4);

 

昨日关注:面对TripleDES,我们别无选择?

2005-4-19

  • [算法&数据结构] 面对Triple DES,我们别无选择? #
    本文详细地讨论了在金融行业普遍使用的DES、Triple DES加解密算法,其中包括正在全球强制执行的EMV标准、ATM上的EPP加密设备、远程密钥管理、迁移到Triple DES的各种费用、银行和ATM厂商需要采取的对策等。本文涉及面很广,几乎覆盖了有关DES的各个方面,也讲了比较深入的技术内容,建议凡是从事金融相关行业的人都抽时间看一下,深入了解EMV及Triple DES标准相关内容,应对国内金融行业迫在眉睫的EMV等标准的实施。
  • [tag] 东拉西扯:tag与关键字 #
    人的思维常常是无序的,跳跃的,同时也是活跃的;但严格的分类法把这种无序的状态进行规整化以后,同时也损失了这种无序所承载的信息量。关键字技术当然是有用的,基于文章的语义分析未来可能产生大量有价值的应用。但,人并不总是需要精确。就像你爱上了一个姑娘,并不是因为她完全符合你事先确定的那些规格,其中一定有很多不可言说的成分。
  • [书签应用] Make Your Own Multipost Bookmarklet Tool #
    Elsewhere I have described a JavaScript bookmarklet tool I cobbled so I can submit websites to multiple tracking sites. Maybe you too want to be able to do a one click submit to send sites to places like Furl or del.icio.us at the same time. (Well at least 2 people emailed me about it). Thus I am inspired to create this tool that allows you to select the ones you want and it will generate the bookmarklet tool for you.
  • [tag] Newsweek Talks Tagging #
    In the article: In the New Game of Tag, All of Us Are It, Newsweek’s Steven Levy talks about the rise of interest in tagging.
  • [tag] Folksonomies – Cooperative Classification and Communication Through Shared Metadata #
    This paper examines user- generated metadata as implemented and applied in two web services designed to share and organize digital media to better understand grassroots classification.
  • [财经股票] 理解交易之道(牧羊) #
    如果道是规律的话,你宁可守着他,决不冒犯。任何冒犯都意味着毁灭,那些前夜的成功者,他们太过于强大,以至于觉得自己可以创造规律,他们以为自己的超人能力能在跨域巅峰之时,可以随意毁掉巅峰,螳螂之臂!最后能留下世人的只有惋惜。
  • [IT业界] IT时评:漫谈Adobe收购Macromedia #
    Macromedia的故事告诉我们两件事:1、后来者应该独自开拓一个市场,或者说抢老大们的未来市场,而不是和老大们硬碰硬;2、要快速建立自己的标准,形成竞争壁垒。这两件事做好了,最差的结局也是被收购,反正不会死掉。
  • [搜索技术] 关注搜索引擎的blog #
    介绍几个关注搜索引擎的blog地址

365Key-天天网摘自动生成

更多新闻,请访问我的365KeyRSS),你可以通过365Key订阅

[导入]Javascript常用正则表达式


匹配中文字符的正则表达式: [\u4e00-\u9fa5]

匹配双字节字符(包括汉字在内): [^\x00-\xff]



应用:计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)

String.prototype.len=function(){return this.replace([^\x00-\xff]/g,&quot;aa&quot;).length;}

匹配空行的正则表达式: \n[\s| ]*\r

匹配HTML标记的正则表达式: /.*|/

匹配首尾空格的正则表达式: (^\s*)|(\s*$)



应用:javascript中没有像vbscript那样的trim函数,我们就可以利用这个表达式来实现,如下:
String.prototype.trim = function() {return this.replace(/(^\s*)|(\s*$)/g, &quot;&quot;);}
利用正则表达式分解和转换IP地址:下面是利用正则表达式匹配IP地址,并将IP地址转换成对应数值的javascript程序:
function IP2V(ip) {re=/(\d+)\.(\d+)\.(\d+)\.(\d+)/g //匹配IP地址的正则表达式
if(re.test(ip)) {return RegExp.*Math.pow(255,3))+RegExp.*Math.pow(255,2))+RegExp.*255+RegExp.*1}else {throw new Error(&quot;Not a valid IP address!&quot;)}}
不过上面的程序如果不用正则表达式,而直接用split函数来分解可能更简单,程序如下:
var ip="10.100.20.168"
ip=ip.split(".")
alert("IP值是:"+(ip[0]*255*255*255+ip[1]*255*255+ip[2]*255+ip[3]*1))
匹配Email地址的正则表达式: \w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*
匹配网址URL的正则表达式: http://([\w-]+\.)+[\w-]+(/[\w- ./ %&amp;=]*) 
利用正则表达式去除字串中重复的字符的算法程序:
var s="abacabefgeeii"var s1=s.replace(/(.).*/g,"")
var re=new RegExp("["+s1+"]","g")
var s2=s.replace(re,"")
alert(s1+s2) //结果为:abcefgi



用正则表达式从URL地址中提取文件名的javascript程序,如下结果为
page1s="http://www.9499.net/page1.htm"s=s.replace(/(.*\/)([^\.]+).*/ig,"")alert(s)
利用正则表达式限制网页表单里的文本框输入内容:
用正则表达式限制只能输入中文:
onkeyup="value=value.replace(/[^\u4E00-\u9FA5]/g,'')"
onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\u4E00-\u9FA5]/g,''))"
用正则表达式限制只能输入全角字符:onkeyup="value=value.replace(/[^\uFF00-\uFFFF]/g,'')"
onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\uFF00-\uFFFF]/g,''))"
用正则表达式限制只能输入数字:onkeyup="value=value.replace(/[^\d]/g,'')
"onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g,''))"
用正则表达式限制只能输入数字和英文:onkeyup="value=value.replace(/[\W]/g,'')
"onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^\d]/g,''))"

文章来源:http://blog.163.com/ccbobo_cat/blog/static/32099462200961005220547

HtmlUnit实现的网站登录

最近坛子里接连出现基于httpclient登录网站的帖子,也凑个热闹,分享一点基于htmlunit的登录经验

谨以此文祭奠我刚刚逝去的鼠标

———————————————-分割线—————————————————
HtmlUnit 目前最新版本2.7(2010-04-15 Foxswily本人确认)
基于httpclient封装(甚至已经做好启用httpclient4的准备),模拟浏览器操作,JavaScript支持较全面,包括主流的jQuery类库,这也是它的强大之处,一般网站的JS屏蔽可以轻松突破。

举例说明

    //创建浏览器,可以选择IE、FF等等
    WebClient client = new WebClient(BrowserVersion.INTERNET_EXPLORER_7);
   
    //获取某网站页面
    HtmlPage page = client.getPage("http://xxx.com");
   
    //获取某页面元素,可通过id或name,(具体方式很多 --Foxswily)
    HtmlElement elmt = page.getElementById("someid");
    //HtmlElement elmt = page.getElementByName("somename");
   
    //此例以文本框为例,先点击,再输入,完全跟真浏览器行为一致
    elmt.click();
    elmt.type("somewords");
   
    //获取按钮
    HtmlButton loginBtn = (HtmlButton)page.getElementById("btnId");
    //点击并获得返回结果
    Page resultPage = loginBtn.click();
    //结果拿到了,想干啥您随意
    log.debug(resultPage.getWebResponse().getContentAsString());
    

 

沿着这个思路展开一下,模拟登录不再需要破解什么js逻辑,用户实际做什么代码就模拟什么,轻松多了   

额外的友情提示,Foxswily本人曾在登录用户量众多的discuz论坛时发现个小问题(已提交bug)

造成登录后跳转失效,如有雷同参照解决吧

问题描述
    HtmlPage.executeRefreshIfNeeded()
when html header has meta like “<META HTTP-EQUIV=”Refresh” CONTENT=”3 URL=h
ttp://www.some.org/some.html”>” it throws NumberFormatException.
cause there is no “;” after “3” in the content.
some forum sites have this bad writting html page.

大意就是,自动跳转格式有问题,htmlunit解析不了,直接Exception了,改写HtmlPage的一个方法后通过。

    private void executeRefreshIfNeeded() throws IOException {
        // If this page is not in a frame then a refresh has already happened,
        // most likely through the JavaScript onload handler, so we don't do a
        // second refresh.
        final WebWindow window = getEnclosingWindow();
        if (window == null) {
            return;
        }

        final String refreshString = getRefreshStringOrNull();
        if (refreshString == null || refreshString.length() == 0) {
            return;
        }

        final double time;
        final URL url;

        int index = refreshString.indexOf(";");
        final boolean timeOnly = (index == -1);

        if (timeOnly && refreshString.indexOf(" ") == -1) {
            // Format: <meta http-equiv='refresh' content='10'>
            try {
                time = Double.parseDouble(refreshString);
            } catch (final NumberFormatException e) {
                if (LOG.isErrorEnabled()) {
                    LOG.error("Malformed refresh string (no ';' but not a number): "
                            + refreshString, e);
                }
                return;
            }
            url = getWebResponse().getRequestSettings().getUrl();
        } else {
            if (refreshString.indexOf(";") == -1) {
                index = refreshString.indexOf(" ");
            }
            // Format: <meta http-equiv='refresh'
            // content='10;url=http://www.blah.com'>
            try {
                time = Double.parseDouble(refreshString.substring(0, index).trim());
            } catch (final NumberFormatException e) {
                if (LOG.isErrorEnabled()) {
                    LOG.error("Malformed refresh string (no valid number before ';') "
                            + refreshString, e);
                }
                return;
            }
            index = refreshString.toLowerCase().indexOf("url=", index);
            if (index == -1) {
                if (LOG.isErrorEnabled()) {
                    LOG.error("Malformed refresh string (found ';' but no 'url='): "
                            + refreshString);
                }
                return;
            }
            final StringBuilder buffer = new StringBuilder(refreshString
                    .substring(index + 4));
            if (buffer.toString().trim().length() == 0) {
                // content='10; URL=' is treated as content='10'
                url = getWebResponse().getRequestSettings().getUrl();
            } else {
                if (buffer.charAt(0) == '"' || buffer.charAt(0) == 0x27) {
                    buffer.deleteCharAt(0);
                }
                if (buffer.charAt(buffer.length() - 1) == '"'
                        || buffer.charAt(buffer.length() - 1) == 0x27) {
                    buffer.deleteCharAt(buffer.length() - 1);
                }
                final String urlString = buffer.toString();
                try {
                    url = getFullyQualifiedUrl(urlString);
                } catch (final MalformedURLException e) {
                    if (LOG.isErrorEnabled()) {
                        LOG.error("Malformed URL in refresh string: " + refreshString, e);
                    }
                    throw e;
                }
            }
        }

        final int timeRounded = (int) time;
        getWebClient().getRefreshHandler().handleRefresh(this, url, timeRounded);
    }

 

学习笔记:JavaScript学习方法建议

JavaScript使网页具有可编程的特性,可编程指通过一定的程序完成一系统列的动作
JavaScript包含:ECMAScript、DOM、BOM

学习方法建议:

1、重视基础,先掌握JavaScript,再学习jQuery或其它的框架
2、学习相关的计算机专业基础课程:高级语言/数据结构/算法基础,程序=数据结构+算法
3、实践+钻研
4、学会提问和寻找答案
5、学会调试

javascript

递归是拖慢脚本运行速度的大敌之一。太多的递归会让浏览器变得越来越慢直到死掉或者莫名其妙的突然自动退出(在firefox中弹出脚本无响应的对话框),所以我们一定要解决在JavaScript中出现的这一系列性能问题。在这个系列文章的第二篇中,我曾经简短的介绍了如何通过memoization技术来替代函数中太多的递归调用。memoization是一种可以缓存之前运算结果的技术,这样我们就不需要重新计算那些已经计算过的结果。对于通过递归来进行计算的函数,memoization简直是太有用了。我现在使用的memoizer是由Crockford写的,主要应用在那些返回整数的递归运算中。当然并不是所有的递归函数都返回整数,所以我们需要一个更加通用的memoizer()函数来处理更多类型的递归函数。

  function memoizer(fundamental, cache){ cache = cache || {} var shell = function(arg){ if (!(arg in cache)){ cache[arg] = fundamental(shell, arg) } return cache[arg]; }; return shell;}这个版本的函数和Crockford写的版本有一点点不同。首先,参数的顺序被颠倒了,原有函数被设置为第一个参数,第二个参数是缓存对象,为可选参数,因为并不是所有的递归函数都包含初始信息。在函数内部,我将缓存对象的类型从数组转换为对象,这样这个版本就可以适应那些不是返回整数的递归函数。在shell函数里,我使用了in操作符来判断参数是否已经包含在缓存里。这种写法比测试类型不是undefined更加安全,因为undefined是一个有效的返回值。我们还是用之前提到的斐波纳契数列来做说明:

  var fibonacci = memoizer(function (recur, n) { return recur(n – 1) + recur(n – 2); }, {“0”:0, “1”:1});同样的,执行fibonacci(40)这个函数,只会对原有的函数调用40次,而不是夸张的331,160,280次。memoization对于那些有着严格定义的结果集的递归算法来说,简直是棒极了。然而,确实还有很多递归算法不适合使用memoization方法来进行优化。

  我在学校时的一位教授一直坚持认为,任何使用递归的情况,如果有需要,都可以使用迭代来代替。实际上,递归和迭代经常会被作为互相弥补的方法,尤其是在另外一种出问题的情况下。将递归算法转换为迭代算法的技术,也是和开发语言无关的。这对JavaScript来说是很重要的,因为很多东西在执行环境中是受到限制的(the importance in JavaScript is greater, though, because the resources of the execution environment are so restrictive.)。让我们回顾一个典型的递归算法,比如说归并排序,在JavaScript中实现这个算法需要下面的代码:

  function merge(left, right){ var result = []; while (left.length > 0 && right.length > 0){ if (left[0] < right[0]){ result.push(left.shift()); } else { result.push(right.shift()); } } return result.concat(left).concat(right);}//采用递归实现的归并排序算法function mergeSort(items){ if (items.length == 1) { return items; } var middle = Math.floor(items.length / 2), left = items.slice(0, middle), right = items.slice(middle); return merge(mergeSort(left), mergeSort(right));}调用mergeSort()函数处理一个数组,就可以返回经过排序的数组。注意每次调用mergeSort()函数,都会有两次递归调用。这个算法不可以使用memoization来进行优化,因为每个结果都只计算并使用一次,就算缓冲了结果也没有什么用。如果你使用mergeSort()函数来处理一个包含100个元素的数组,总共会有199次调用。1000个元素的数组将会执行1999次调用。在这种情况下,我们的解决方案是将递归算法转换为迭代算法,也就是说要引入一些循环(关于算法,可以参考这篇《List Processing: Sort Again, Naturally》)。

[编辑本段]

Javascript 与 JScript

  JScript是Microsoft公司开发的,Javascript是Sun公司开发的.虽然他们是死对头,但是在现在的浏览器中,无论你把语言指定为Javascript 还是 Jscript, 浏览器都会综合他们两个语言的特性.所以,即使把语言指定为Javascript, 用几句JScript也是没问题的.

  虽然浏览器综合和两种语言的特性,但是对脚本语言熟悉的程序员还是会说Jscript的实用性更强. 如果你在网上察看Javascript 和 Jscript 的手册,你会发现Jscript的运算符比Javascript多得多, 所以许多库(比如Concurrent.Thread)都是采用Jscript的格式编写的.