本文通過比較對(duì)數(shù)字指定誤差的求開平方不同算法實(shí)現(xiàn)之間的效率比較,來使程序入門者對(duì)不同算法的性能差距有直觀的印象,并且對(duì)算法的作用有深刻的體會(huì)。
算法一(暴力遍歷法):
/** * 求開方 * @param source 被開方數(shù),大于等于0 * @param deviation 誤差范圍 * @return */ public static double sqrt(double source,double deviation) { if(source < 0 || deviation <0) { throw new RuntimeException("don't transmit negtive"); } long count = 1;//統(tǒng)計(jì)循環(huán)執(zhí)行次數(shù) double result = 0; while ((result + 1) * (result + 1) < source) { count++; result++; } while ((result + deviation) * (result + deviation) < source ) { count++; result += deviation; } System.out.PRintln("sqrt total count:" + count); return result; }本算法是將計(jì)算結(jié)果從0開始一點(diǎn)一點(diǎn)增加并進(jìn)行試探,直到接近真實(shí)結(jié)果誤差范圍內(nèi)。
算法二(步長(zhǎng)調(diào)整法):
/** * 求開方 優(yōu)化,步長(zhǎng)調(diào)整 * @param source 被開方數(shù),大于等于0 * @param deviation 誤差范圍 * @return */ public static double sqrt1(double source,double deviation) { if(source < 0 || deviation <0) { throw new RuntimeException("don't transmit negtive"); } long count = 1;//統(tǒng)計(jì)循環(huán)執(zhí)行次數(shù) double result = 0; int stepI = 2; double stepD = deviation; long stepCount = 1; while ((result + 1) * (result + 1) < source) { count++; stepCount++; if(stepCount%3==0){ //加快結(jié)果累計(jì),調(diào)整步長(zhǎng) if((result + stepI) * (result + stepI) < source) { result += stepI; stepI++; continue; } else { stepI--; } } result++; } stepCount = 0; while ((result + deviation) * (result + deviation) < source ) { count++; stepCount++; if(stepCount%3==0){ //加快結(jié)果累計(jì),調(diào)整步長(zhǎng) if((result + stepD) * (result + stepD) < source) { result += stepD; stepD+=deviation; continue; } else { stepD-=deviation; } } result += deviation; } System.out.println("sqrt1 total count :" + count); return result; }本算法每當(dāng)執(zhí)行循環(huán)三次時(shí)調(diào)整一次步長(zhǎng),讀者可以自行定制更加高效的調(diào)整步長(zhǎng)策略。
算法三(二分法):
/** * 求開方 優(yōu)化,二分法 * 該方法效率明顯比前兩個(gè)方法快的多 * @param source 被開方數(shù),大于等于0 * @param deviation 誤差范圍 * @return */ public static double sqrt2(double source,double deviation) { if(source < 0 || deviation <0) { throw new RuntimeException("don't transmit negtive"); } long count = 1;//統(tǒng)計(jì)循環(huán)執(zhí)行次數(shù) double result = 0; double head = source; double tail = 0; while(true) { count++; if(((head+tail)/2) * ((head+tail)/2) < source) { tail = (head+tail)/2; } else { head = (head+tail)/2; } result = (head+tail)/2; if((result + deviation)*(result + deviation) >= source && (result - deviation)*(result - deviation) <= source) { break; } } System.out.println("sqrt2 total count:" + count); return result; }本算法為典型的二分法,算法的原理如下:將0和source分別作為結(jié)果的初始下界和上界,將下界和上界的平均值與真實(shí)結(jié)果比較并調(diào)整結(jié)果的下界或者上界,直至結(jié)果位于真實(shí)結(jié)果的誤差范圍內(nèi)。
上面已經(jīng)給出了算法的實(shí)現(xiàn),算法可能的難點(diǎn)是怎么判斷算出的值是否在誤差范圍內(nèi),讀者需要注意這點(diǎn)。下面通過幾組數(shù)據(jù)簡(jiǎn)單的比較一下不同算法實(shí)現(xiàn)之間的效率差別:
上圖中,我們測(cè)試了三組數(shù)據(jù),從標(biāo)紅的數(shù)據(jù)可以看出,算法二明顯優(yōu)于算法一,而算法三明顯優(yōu)于算法二。當(dāng)執(zhí)行第三組數(shù)據(jù)時(shí),算法一甚至要等一小會(huì)兒才能執(zhí)行完,而算法三卻馬上就能得到結(jié)果,而且算法三隨著問題規(guī)模的擴(kuò)大執(zhí)行次數(shù)卻增長(zhǎng)很慢,而這只是簡(jiǎn)單的幾行代碼改進(jìn)的結(jié)果。從這個(gè)算法問題中我們可以看到不同算法之間效率的巨大差距,由此不難體會(huì)在許多算法應(yīng)用場(chǎng)合下算法巨大的威力。
新聞熱點(diǎn)
疑難解答
圖片精選
網(wǎng)友關(guān)注