Next talk about biginteger-Optimization

Source: Internet
Author: User
ArticleDirectory
    • References:

In the previous article "gethashcode", I implemented a new skyiv. Numeric. biginteger. gethashcode method:

 
Public override intGethashcode (){IntN = sign;For(IntI = data. Length-1; I> = 0; I-= 4 ){IntM = data [I];If(I> 0) M | = (data [I-1] <8 );If(I> 1) M | = (data [I-2] <16 );If(I> 2) M | = (data [I-3] <24); n = m ^ (n + (n <5) + (n> 0x1b ));}ReturnN * 0x5d588b65 ;}

the Code is elegant, but the If statements in the blue "> for loop can actually mention for outside the loop, as shown below:

Public override intGethashcode (){IntN = sign, I;For(I = data. length-1; I> = 4; I-= 4) n = (data [I] | (data [I-1] <8) | (data [I-2] <16) | (data [I-3] <24) ^ (n + (n <5) + (n> 27 ));If(I> = 0 ){IntM = data [I];If(I> 0) M | = (data [I-1] <8 );If(I> 1) M | = (data [I-2] <16 );If(I> 2) M | = (data [I-3] <24); n = m ^ (n + (n <5) + (n> 27 ));}ReturnN * 0x5d588b65 ;}

Although the above Code is not so elegant and has repeated "Bad taste", it is more efficient. Let's test it:

 Using System;Using System. diagnostics; Using  Biginteger = Skyiv. Numeric. Biginteger ; Namespace Skyiv { Class  Testmain { Static void Main ( String [] ARGs ){ Try { VaR Stopwatch = Stopwatch . Startnew (); VaR S = New String ( '7' , (ARGs. length> 0 )? Int . Parse (ARGs [0]): 1000000 ); VaR N = Biginteger . Parse (s); stopwatch. Stop (); writeline ( "Parse digits" , S. length, stopwatch. elapsed); testgethashcode (n, True ); Testgethashcode (n, False );} Catch ( Exception Ex ){Console . Writeline (Ex );}} Static void Testgethashcode ( Biginteger N, Bool Isfast ){ VaR Stopwatch = Stopwatch . Startnew (); VaR Hash = n. gethashcode (isfast); stopwatch. Stop (); writeline (isfast? "Fast hashcode" : "Simple hashcode" , Hash, stopwatch. elapsed );} Static void Writeline (String Item, Int Value, Timespan SPAN ){ Console . Writeline ( "{}:{: N0} elapsed: {: F7 }" , Item, value, span. totalseconds );}}}

The test results are as follows:

E: \ CS \ biginteger> biginteger 600000000 parse digits: 600,000,000 elapsed: 254.8271638 fast hashcode: 353,915,569 elapsed: 1.5341352 simple hashcode: 353,915,569 elapsed: 1.7766916

First, use the biginteger. parse method to generate an integer with 0.6 billion digits (in 254.83 seconds). Then:

    • Call the new gethashcode method. The returned value is 353,915,569, which takes 1.53 seconds.
    • Call the old gethashcode method. The returned value is 353,915,569, and it takes 1.77 seconds.

It can be seen that the new gethashcode method is indeed more efficient, but it does not improve much, and it also loses the elegance of the Code.

 

How does the biginteger. parse method consume so much time? Check the sourceProgram:

 Public static  Biginteger Parse ( String S ){ If (S = Null ) Return null ; If (S. Length = 0) Return 0; Biginteger Z =New  Biginteger (); Z. Sign = ( Sbyte ) (S [0] = '-' )? -1: 1 ); If (S [0] = '-' | S [0] = '+' ) S = S. substring (1 ); Int R = S. Length % Len; Z. Data = New byte [S. Length/Len + (R! = 0 )? 1: 0)]; Int I = 0; If (R! = 0) Z. Data [I ++] = Byte . Parse (S. substring (0, R )); For (; I <Z. Data. length; I ++, R + = Len) Z. Data [I] = Byte . Parse (S. substring (R, Len); Z. Shrink (); Return Z ;}

The most time-consuming parse method isForLoop, So rewrite thisForLoop, replacing time-consuming with simple mathematical computingByteThe. parse method is as follows:

 
For(; I <Z. Data. length; I ++, R + = Len) Z. Data [I] = (Byte) (S [R]-'0') * 10 + (s [R + 1]-'0'));

Run the test program again. The result is as follows:

E: \ CS \ biginteger> biginteger 600000000 parse digits: 600,000,000 elapsed: 11.0663091 fast hashcode: 353,915,569 elapsed: 1.5217181 simple hashcode: 353,915,569 elapsed: 1.7744348

The result is reduced from 254.83 seconds to 11.07 seconds, which greatly improves the efficiency and keeps the code elegant. This is a very successful optimization.

 

The CPU usage and memory usage of the two tests are as follows:

 

Next, let's take a look at the tostring method:

Public override stringTostring (){VaRSB =NewStringbuilder();If(Sign <0) sb. append ('-'); Sb. append (data. Length = 0 )? 0 :(Int) Data [0]);For(VaRI = 1; I <data. length; I ++) sb. append (data [I]. tostring ("D"+ Len ));ReturnSB. tostring ();}

This can also be optimized as follows:

 Public override string Tostring (){ If (Data. Length = 0) Return  "0" ;VaR SB = New  Stringbuilder (Length, length); sb. Length = length; VaR K = 0; If (Sign <0) Sb [k ++] = '-' ; If (Data [0]> = 10) Sb [k ++] = ( Char ) (Data [0]/10 + '0' ); Sb [k ++] = ( Char ) (Data [0] % 10 + '0' ); For (VaR I = 1; I <data. length; I ++) {Sb [k ++] = ( Char ) (Data [I]/10 + '0' ); Sb [k ++] = ( Char ) (Data [I] % 10 + '0' );} Return SB. tostring ();} Public int Length { Get { Return (Data. Length = 0 )? 1: (sign <0 )? 1: 0) + (data [0] <10 )? -1: 0) + data. length * Len );}}

The following are the test results before optimization:

E: \ CS \ biginteger> biginteger 100000000 tostring digits: 100,000,000 elapsed: 99.4138987 fast hashcode: 1,470,973,525 elapsed: 0.2504019 simple hashcode: 1,470,973,525 elapsed: 0.2944836

After optimization:

E: \ CS \ biginteger> biginteger 100000000 tostring digits: 100,000,000 elapsed: 10.1196895 fast hashcode: 1,470,973,525 elapsed: 0.2530704 simple hashcode: 1,470,973,525 elapsed: 0.2957576

It can be seen that the tostring method is called to output an integer with 0.1 billion digits, which reduces the time consumption from the original 99.41 seconds to the optimized 10.12 seconds. The effect is remarkable. In addition, the memory usage of the optimized tostring method is greatly reduced.

 

References:
    1. Let's talk about biginteger-using Fast Fourier Transformation
    2. About biginteger
    3. Gethashcode

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.