再談 BigInteger 優化

2021-09-05 23:30:51 字數 2727 閱讀 9642

在上篇隨筆「** gethashcode」中,我實現了乙個新的 skyiv.numeric.biginteger.gethashcode 方法:

public override int gethashcode()

return n * 0x5d588b65;

}

上述**比較優雅,但是在 for 迴圈中的三個 if 語句其實可以提到 for 迴圈外面的,如下所示:

public override int gethashcode()

return n * 0x5d588b65;

}

雖然以上**不那麼優雅,有重複的「壞味道」,但是效率更高了。我們來實際測試一下吧:

using system;

using system.diagnostics;

using

biginteger = skyiv.numeric.biginteger;

namespace skyiv

catch (exception ex)

}static void testgethashcode(biginteger n, bool isfast)

static void writeline(string item, int value, timespan span)

: elapsed: ", item, value, span.totalseconds);}}}

測試結果如下所示:

e:\cs\biginteger> biginteger 600000000

parse digits: 600,000,000 elapsed: 254.8271638

fast hashcode: 353,915,569 elapsed: 1.5341352

****** hashcode: 353,915,569 elapsed: 1.7766916

首先使用 biginteger.parse 方法生成乙個有六億位數字的整數(用時 254.83 秒),然後:

可見,新的 gethashcode 方法的效率的確更高,但是提高的幅度也不多,而且還損失了**的優雅性。

怎麼 biginteger.parse 方法耗時這麼多?去看看源程式:

public static 

biginteger parse(string s)

這個 parse 方法中耗時最多的就是 for 迴圈,於是,改寫這個 for 迴圈,用簡單的數學計算代替費時的 byte.parse 方法,如下所示:

for (; i < z.data.length; i++, r += len) z.data[i] = (byte)((s[r] - '0') * 10 + (s[r + 1] - '0'));
然後重新執行測試程式,結果如下:

e:\cs\biginteger> biginteger 600000000

parse digits: 600,000,000 elapsed: 11.0663091

fast hashcode: 353,915,569 elapsed: 1.5217181

****** hashcode: 353,915,569 elapsed: 1.7744348

結果用時從 254.83 秒下降到 11.07 秒,效率得到了極大地提高,而且**還保持了優雅。這是一次非常成功的優化。 :)

這兩次測試的 cpu 占用和記憶體使用情況如下所示:

接著,我們來看看 tostring 方法:

public override string tostring()

這也可以優化如下:

public override string tostring()

return sb.tostring();

}public int length

}

下面是優化之前測試結果:

e:\cs\biginteger> biginteger 100000000

tostring digits: 100,000,000 elapsed: 99.4138987

fast hashcode: 1,470,973,525 elapsed: 0.2504019

****** hashcode: 1,470,973,525 elapsed: 0.2944836

優化之後:

e:\cs\biginteger> biginteger 100000000

tostring digits: 100,000,000 elapsed: 10.1196895

fast hashcode: 1,470,973,525 elapsed: 0.2530704

****** hashcode: 1,470,973,525 elapsed: 0.2957576

可以看出,呼叫 tostring 方法將乙個有一億位數字的整數輸出,耗時從原來的 99.41 秒下降到優化後的 10.12 秒,效果很是顯著。不但如此,優化後的 tostring 方法記憶體占用也大為減少。

BigInteger建構函式解析

1 biginteger byte val 這個建構函式用於轉換乙個位元組陣列包含biginteger的二進位制補碼,以二進位制表示成乙個biginteger。用位元組陣列中值的ascii碼構造biginteger 2 biginteger int signum,byte magnitude 此建構...

大整數類運算 BigInteger

當數字超出型別上限就會出現溢位的情形。如果運算結果真的很大,那就需要運用到所謂的高精度運算,即用陣列來儲存整數,然後模擬手算的形式來實現。但還應考慮乙個易用性的問題 如果能像使用int一樣方便地使用大整數那該多好!那就是使用struct!結構體biginteger可用於儲存高精度非負整數 1 2 3...

BigInteger存資料的方式

問題源於乙個面試問題,當乙個long型別值乘以乙個long型別的值,需要用什麼來接收,當時第一時間想到用biginteger型別來接收,但是面試官的問題並不是說讓用封裝完成的類來接收,一時語塞!說下biginteger的存資料的方式,也沒有答上來,回來研究biginteger的底層操作才明白。其實在...