Author:水如烟
哇噻。真快了好多。
算到1000的阶乘只用25秒。且全是在一个线程里面。
现在算10000的阶乘不是问题了.在另一台机运算了一个小时,算到了9300多,数据位33000多.这时的速度约一秒一个.
算到36106时,数据位为148879,现在的速度是2秒一个,其中包括了写入数据库的时间.
下面的代码在处理分拆时还是不妥的.
现在需要转到值片断的表示问题.
数据一大,需要考虑的问题真的多多.
<
Serializable()
>
_
Public Class MathsUnit
Private gMathUnits As New Collections.ObjectModel.Collection( Of MathUnit) ' 运算单元组
Private gLocalIndex As Integer = 0 ' 当前组最后运算单元在全部运算单元中的位置。从最后往前数(就是从个位开始数)。
Private gHasCarry As Boolean = False ' 是否有进位
Private gCarry As New MathUnit( True ) ' 进位运算单元
Public ReadOnly Property fullvalue() As String
Get
Dim b As New system.text.stringbuilder
If ghascarry Then b.append(gcarry.value)
b.append(value)
Return b.tostring
End Get
End Property
Public ReadOnly Property Value() As String
Get
Dim b As New System.Text.StringBuilder
For i As Integer = 0 To gMathUnits.Count - 1
b.Append(gMathUnits(i).Value)
Next
Return b.ToString
End Get
End Property
Public Sub SetValue( ByVal strUnit As StringUnit)
Me .Clear()
Dim strArray() As String = Information.SplitValueToArray(strUnit.Value)
Dim mMathUnit As MathUnit
For i As Integer = 0 To strArray.Length - 1
If i = 0 Then
mMathUnit = New MathUnit( True )
Else
mMathUnit = New MathUnit
End If
mMathUnit.SetValue(strArray(i))
Me .gMathUnits.Add(mMathUnit)
Next
gLocalIndex = strUnit.LocalIndex
End Sub
Private Sub Clear()
gMathUnits.Clear()
gLocalIndex = 0
gHasCarry = False
gCarry.Clear()
End Sub
Public Function Clone() As MathsUnit
Return CommonFunction.Clone( Of MathsUnit)( Me )
End Function
Public Sub CopyFrom( ByVal unit As MathsUnit)
With unit
gMathUnits.Clear()
For i As Integer = 0 To .gMathUnits.Count - 1
gMathUnits.Add(.gMathUnits(i).Clone)
Next
gLocalIndex = .gLocalIndex
gHasCarry = .gHasCarry
gCarry = .gCarry.Clone
End With
End Sub
End Class
Public Class MathsUnit
Private gMathUnits As New Collections.ObjectModel.Collection( Of MathUnit) ' 运算单元组
Private gLocalIndex As Integer = 0 ' 当前组最后运算单元在全部运算单元中的位置。从最后往前数(就是从个位开始数)。
Private gHasCarry As Boolean = False ' 是否有进位
Private gCarry As New MathUnit( True ) ' 进位运算单元
Public ReadOnly Property fullvalue() As String
Get
Dim b As New system.text.stringbuilder
If ghascarry Then b.append(gcarry.value)
b.append(value)
Return b.tostring
End Get
End Property
Public ReadOnly Property Value() As String
Get
Dim b As New System.Text.StringBuilder
For i As Integer = 0 To gMathUnits.Count - 1
b.Append(gMathUnits(i).Value)
Next
Return b.ToString
End Get
End Property
Public Sub SetValue( ByVal strUnit As StringUnit)
Me .Clear()
Dim strArray() As String = Information.SplitValueToArray(strUnit.Value)
Dim mMathUnit As MathUnit
For i As Integer = 0 To strArray.Length - 1
If i = 0 Then
mMathUnit = New MathUnit( True )
Else
mMathUnit = New MathUnit
End If
mMathUnit.SetValue(strArray(i))
Me .gMathUnits.Add(mMathUnit)
Next
gLocalIndex = strUnit.LocalIndex
End Sub
Private Sub Clear()
gMathUnits.Clear()
gLocalIndex = 0
gHasCarry = False
gCarry.Clear()
End Sub
Public Function Clone() As MathsUnit
Return CommonFunction.Clone( Of MathsUnit)( Me )
End Function
Public Sub CopyFrom( ByVal unit As MathsUnit)
With unit
gMathUnits.Clear()
For i As Integer = 0 To .gMathUnits.Count - 1
gMathUnits.Add(.gMathUnits(i).Clone)
Next
gLocalIndex = .gLocalIndex
gHasCarry = .gHasCarry
gCarry = .gCarry.Clone
End With
End Sub
End Class
Partial
Class
MathsUnit
Public Shared Operator = ( ByVal a As MathsUnit, ByVal b As MathsUnit) As Boolean
If a.gLocalIndex <> b.gLocalIndex Then Return False
If a.gMathUnits.Count <> b.gMathUnits.Count Then Return False
For i As Integer = 0 To a.gMathUnits.Count - 1
If a.gMathUnits(i) <> b.gMathUnits(i) Then Return False
Next
If a.gHasCarry <> b.gHasCarry Then Return False
If a.gCarry <> b.gCarry Then Return False
Return True
End Operator
Public Shared Operator <> ( ByVal a As MathsUnit, ByVal b As MathsUnit) As Boolean
If a.gLocalIndex <> b.gLocalIndex Then Return True
If a.gMathUnits.Count <> b.gMathUnits.Count Then Return True
For i As Integer = 0 To a.gMathUnits.Count - 1
If a.gMathUnits(i) <> b.gMathUnits(i) Then Return True
Next
If a.gHasCarry <> b.gHasCarry Then Return True
If a.gCarry <> b.gCarry Then Return True
Return True
End Operator
Public Shared Operator > ( ByVal a As MathsUnit, ByVal b As MathsUnit) As Boolean
If a.gLocalIndex > b.gLocalIndex Then Return True
If a.gLocalIndex < b.gLocalIndex Then Return False
If a.gMathUnits.Count > b.gMathUnits.Count Then Return True
If a.gMathUnits.Count < b.gMathUnits.Count Then Return False
For i As Integer = 0 To a.gMathUnits.Count - 1
If a.gMathUnits(i) > b.gMathUnits(i) Then Return True
If a.gMathUnits(i) < b.gMathUnits(i) Then Return False
Next
Return a.gCarry > b.gCarry
End Operator
Public Shared Operator >= ( ByVal a As MathsUnit, ByVal b As MathsUnit) As Boolean
If a.gLocalIndex > b.gLocalIndex Then Return True
If a.gLocalIndex < b.gLocalIndex Then Return False
If a.gMathUnits.Count > b.gMathUnits.Count Then Return True
If a.gMathUnits.Count < b.gMathUnits.Count Then Return False
For i As Integer = 0 To a.gMathUnits.Count - 1
If a.gMathUnits(i) > b.gMathUnits(i) Then Return True
If a.gMathUnits(i) < b.gMathUnits(i) Then Return False
Next
Return a.gCarry >= b.gCarry
End Operator
Public Shared Operator < ( ByVal a As MathsUnit, ByVal b As MathsUnit) As Boolean
If a.gLocalIndex > b.gLocalIndex Then Return False
If a.gLocalIndex < b.gLocalIndex Then Return True
If a.gMathUnits.Count > b.gMathUnits.Count Then Return False
If a.gMathUnits.Count < b.gMathUnits.Count Then Return True
For i As Integer = 0 To a.gMathUnits.Count - 1
If a.gMathUnits(i) > b.gMathUnits(i) Then Return False
If a.gMathUnits(i) < b.gMathUnits(i) Then Return True
Next
Return a.gCarry < b.gCarry
End Operator
Public Shared Operator <= ( ByVal a As MathsUnit, ByVal b As MathsUnit) As Boolean
If a.gLocalIndex > b.gLocalIndex Then Return False
If a.gLocalIndex < b.gLocalIndex Then Return True
If a.gMathUnits.Count > b.gMathUnits.Count Then Return False
If a.gMathUnits.Count < b.gMathUnits.Count Then Return True
For i As Integer = 0 To a.gMathUnits.Count - 1
If a.gMathUnits(i) > b.gMathUnits(i) Then Return False
If a.gMathUnits(i) < b.gMathUnits(i) Then Return True
Next
Return a.gCarry <= b.gCarry
End Operator
Public Shared Function Max( ByVal a As MathsUnit, ByVal b As MathsUnit) As MathsUnit
If a >= b Then
Return a
Else
Return b
End If
End Function
End Class
Public Shared Operator = ( ByVal a As MathsUnit, ByVal b As MathsUnit) As Boolean
If a.gLocalIndex <> b.gLocalIndex Then Return False
If a.gMathUnits.Count <> b.gMathUnits.Count Then Return False
For i As Integer = 0 To a.gMathUnits.Count - 1
If a.gMathUnits(i) <> b.gMathUnits(i) Then Return False
Next
If a.gHasCarry <> b.gHasCarry Then Return False
If a.gCarry <> b.gCarry Then Return False
Return True
End Operator
Public Shared Operator <> ( ByVal a As MathsUnit, ByVal b As MathsUnit) As Boolean
If a.gLocalIndex <> b.gLocalIndex Then Return True
If a.gMathUnits.Count <> b.gMathUnits.Count Then Return True
For i As Integer = 0 To a.gMathUnits.Count - 1
If a.gMathUnits(i) <> b.gMathUnits(i) Then Return True
Next
If a.gHasCarry <> b.gHasCarry Then Return True
If a.gCarry <> b.gCarry Then Return True
Return True
End Operator
Public Shared Operator > ( ByVal a As MathsUnit, ByVal b As MathsUnit) As Boolean
If a.gLocalIndex > b.gLocalIndex Then Return True
If a.gLocalIndex < b.gLocalIndex Then Return False
If a.gMathUnits.Count > b.gMathUnits.Count Then Return True
If a.gMathUnits.Count < b.gMathUnits.Count Then Return False
For i As Integer = 0 To a.gMathUnits.Count - 1
If a.gMathUnits(i) > b.gMathUnits(i) Then Return True
If a.gMathUnits(i) < b.gMathUnits(i) Then Return False
Next
Return a.gCarry > b.gCarry
End Operator
Public Shared Operator >= ( ByVal a As MathsUnit, ByVal b As MathsUnit) As Boolean
If a.gLocalIndex > b.gLocalIndex Then Return True
If a.gLocalIndex < b.gLocalIndex Then Return False
If a.gMathUnits.Count > b.gMathUnits.Count Then Return True
If a.gMathUnits.Count < b.gMathUnits.Count Then Return False
For i As Integer = 0 To a.gMathUnits.Count - 1
If a.gMathUnits(i) > b.gMathUnits(i) Then Return True
If a.gMathUnits(i) < b.gMathUnits(i) Then Return False
Next
Return a.gCarry >= b.gCarry
End Operator
Public Shared Operator < ( ByVal a As MathsUnit, ByVal b As MathsUnit) As Boolean
If a.gLocalIndex > b.gLocalIndex Then Return False
If a.gLocalIndex < b.gLocalIndex Then Return True
If a.gMathUnits.Count > b.gMathUnits.Count Then Return False
If a.gMathUnits.Count < b.gMathUnits.Count Then Return True
For i As Integer = 0 To a.gMathUnits.Count - 1
If a.gMathUnits(i) > b.gMathUnits(i) Then Return False
If a.gMathUnits(i) < b.gMathUnits(i) Then Return True
Next
Return a.gCarry < b.gCarry
End Operator
Public Shared Operator <= ( ByVal a As MathsUnit, ByVal b As MathsUnit) As Boolean
If a.gLocalIndex > b.gLocalIndex Then Return False
If a.gLocalIndex < b.gLocalIndex Then Return True
If a.gMathUnits.Count > b.gMathUnits.Count Then Return False
If a.gMathUnits.Count < b.gMathUnits.Count Then Return True
For i As Integer = 0 To a.gMathUnits.Count - 1
If a.gMathUnits(i) > b.gMathUnits(i) Then Return False
If a.gMathUnits(i) < b.gMathUnits(i) Then Return True
Next
Return a.gCarry <= b.gCarry
End Operator
Public Shared Function Max( ByVal a As MathsUnit, ByVal b As MathsUnit) As MathsUnit
If a >= b Then
Return a
Else
Return b
End If
End Function
End Class
左、右补位:
Partial
Class
MathsUnit
Private Sub RightMakeUpUnits( ByVal amount As Integer )
If amount < 1 Then Exit Sub
If gLocalIndex - amount < 0 Then Throw New Exception(Information.MSG_UNIT_MUTIPLY_MOVE_OVERFLOW)
For i As Integer = 0 To amount - 1
gMathUnits.Add( New MathUnit)
Next
gLocalIndex -= amount
End Sub
Private Sub LeftMakeUpUnits( ByVal amount As Integer )
If amount < 1 Then Exit Sub
If gMathUnits.Count > 0 Then gMathUnits( 0 ).IsFirstUnitReverse()
For i As Integer = 0 To amount - 1
gMathUnits.Insert( 0 , New MathUnit)
Next
gMathUnits( 0 ).IsFirstUnitReverse()
If gHasCarry Then
gMathUnits(amount - 1 ).Add(gCarry)
gCarry.Clear()
gHasCarry = False
End If
End Sub
Private Sub FullMakeUpUnits( ByVal unit As MathsUnit)
RightMakeUpUnits( Me .gLocalIndex - unit.gLocalIndex)
LeftMakeUpUnits(unit.gLocalIndex + unit.gMathUnits.Count - Me .gLocalIndex - Me .gMathUnits.Count)
End Sub
End Class
Private Sub RightMakeUpUnits( ByVal amount As Integer )
If amount < 1 Then Exit Sub
If gLocalIndex - amount < 0 Then Throw New Exception(Information.MSG_UNIT_MUTIPLY_MOVE_OVERFLOW)
For i As Integer = 0 To amount - 1
gMathUnits.Add( New MathUnit)
Next
gLocalIndex -= amount
End Sub
Private Sub LeftMakeUpUnits( ByVal amount As Integer )
If amount < 1 Then Exit Sub
If gMathUnits.Count > 0 Then gMathUnits( 0 ).IsFirstUnitReverse()
For i As Integer = 0 To amount - 1
gMathUnits.Insert( 0 , New MathUnit)
Next
gMathUnits( 0 ).IsFirstUnitReverse()
If gHasCarry Then
gMathUnits(amount - 1 ).Add(gCarry)
gCarry.Clear()
gHasCarry = False
End If
End Sub
Private Sub FullMakeUpUnits( ByVal unit As MathsUnit)
RightMakeUpUnits( Me .gLocalIndex - unit.gLocalIndex)
LeftMakeUpUnits(unit.gLocalIndex + unit.gMathUnits.Count - Me .gLocalIndex - Me .gMathUnits.Count)
End Sub
End Class
进位处理:
Partial
Class
MathsUnit
Private Sub ReferCarry()
For i As Integer = 0 To Me .gMathUnits.Count - 1
ReferCarry(i)
Next
gHasCarry = (gCarry.Value <> " 0 " )
End Sub
Private Sub ReferCarry( ByVal index As Integer )
Dim mCurrentMathUnit As MathUnit = gMathUnits(index)
Dim mPreviousMathUnit As MathUnit
If mCurrentMathUnit.HasCarry Then
If index = 0 Then
mPreviousMathUnit = gCarry
Else
mPreviousMathUnit = gMathUnits(index - 1 )
End If
mCurrentMathUnit.ReferCarryTo(mPreviousMathUnit)
If mPreviousMathUnit.HasCarry Then
ReferCarry(index - 1 )
End If
End If
End Sub
End Class
Private Sub ReferCarry()
For i As Integer = 0 To Me .gMathUnits.Count - 1
ReferCarry(i)
Next
gHasCarry = (gCarry.Value <> " 0 " )
End Sub
Private Sub ReferCarry( ByVal index As Integer )
Dim mCurrentMathUnit As MathUnit = gMathUnits(index)
Dim mPreviousMathUnit As MathUnit
If mCurrentMathUnit.HasCarry Then
If index = 0 Then
mPreviousMathUnit = gCarry
Else
mPreviousMathUnit = gMathUnits(index - 1 )
End If
mCurrentMathUnit.ReferCarryTo(mPreviousMathUnit)
If mPreviousMathUnit.HasCarry Then
ReferCarry(index - 1 )
End If
End If
End Sub
End Class
Partial
Class
MathsUnit
Public Sub Add( ByVal unit As MathsUnit)
If unit Is Nothing Then Exit Sub
Me .FullMakeUpUnits(unit)
Dim mMathUnitCount As Integer = unit.gMathUnits.Count
Dim bIndex As Integer
Dim k As Integer = 0
Dim CurrentMathUnit As MathUnit
For i As Integer = Me .gMathUnits.Count - 1 To 0 Step - 1
bIndex = mMathUnitCount - 1 - k
If bIndex < 0 Then
CurrentMathUnit = Nothing
Else
CurrentMathUnit = unit.gMathUnits(bIndex)
End If
Me .gMathUnits(i).Add(CurrentMathUnit)
k += 1
Next
Me .ReferCarry()
If gHasCarry Then Me .LeftMakeUpUnits( 1 )
End Sub
Public Shared Operator + ( ByVal a As MathsUnit, ByVal b As MathsUnit) As MathsUnit
Dim c As MathsUnit = a.Clone
c.Add(b)
Return c
End Operator
End Class
Public Sub Add( ByVal unit As MathsUnit)
If unit Is Nothing Then Exit Sub
Me .FullMakeUpUnits(unit)
Dim mMathUnitCount As Integer = unit.gMathUnits.Count
Dim bIndex As Integer
Dim k As Integer = 0
Dim CurrentMathUnit As MathUnit
For i As Integer = Me .gMathUnits.Count - 1 To 0 Step - 1
bIndex = mMathUnitCount - 1 - k
If bIndex < 0 Then
CurrentMathUnit = Nothing
Else
CurrentMathUnit = unit.gMathUnits(bIndex)
End If
Me .gMathUnits(i).Add(CurrentMathUnit)
k += 1
Next
Me .ReferCarry()
If gHasCarry Then Me .LeftMakeUpUnits( 1 )
End Sub
Public Shared Operator + ( ByVal a As MathsUnit, ByVal b As MathsUnit) As MathsUnit
Dim c As MathsUnit = a.Clone
c.Add(b)
Return c
End Operator
End Class
Partial
Class
MathsUnit
Public Sub Multy( ByVal unit As MathsUnit)
Dim mCount As Integer = unit.gMathUnits.Count
Dim mResultArray(mCount - 1 ) As MathsUnit
For i As Integer = 0 To mCount - 1
mResultArray(i) = MultiplyUnit(unit.gMathUnits(i))
mResultArray(i).RightMakeUpUnitsWhenMultiply(unit, mCount - 1 - i)
Next
For i As Integer = 1 To mCount - 1
mResultArray( 0 ).Add(mResultArray(i))
Next
Me .CopyFrom(mResultArray( 0 ))
End Sub
Public Shared Operator * ( ByVal a As MathsUnit, ByVal b As MathsUnit) As MathsUnit
Dim c As MathsUnit = a.Clone
c.Multy(b)
Return c
End Operator
Private Function MultiplyUnit( ByVal unit As MathUnit) As MathsUnit
Dim mResult As MathsUnit = Me .Clone
For i As Integer = 0 To mResult.gMathUnits.Count - 1
mResult.gMathUnits(i).Multy(unit)
Next
mResult.ReferCarry()
If mResult.gHasCarry Then mResult.LeftMakeUpUnits( 1 )
Return mResult
End Function
Private Sub RightMakeUpUnitsWhenMultiply( ByVal b As MathsUnit, ByVal indexOfMathunitFromLast As Integer )
Me .gLocalIndex += indexOfMathunitFromLast
End Sub
End Class
Public Sub Multy( ByVal unit As MathsUnit)
Dim mCount As Integer = unit.gMathUnits.Count
Dim mResultArray(mCount - 1 ) As MathsUnit
For i As Integer = 0 To mCount - 1
mResultArray(i) = MultiplyUnit(unit.gMathUnits(i))
mResultArray(i).RightMakeUpUnitsWhenMultiply(unit, mCount - 1 - i)
Next
For i As Integer = 1 To mCount - 1
mResultArray( 0 ).Add(mResultArray(i))
Next
Me .CopyFrom(mResultArray( 0 ))
End Sub
Public Shared Operator * ( ByVal a As MathsUnit, ByVal b As MathsUnit) As MathsUnit
Dim c As MathsUnit = a.Clone
c.Multy(b)
Return c
End Operator
Private Function MultiplyUnit( ByVal unit As MathUnit) As MathsUnit
Dim mResult As MathsUnit = Me .Clone
For i As Integer = 0 To mResult.gMathUnits.Count - 1
mResult.gMathUnits(i).Multy(unit)
Next
mResult.ReferCarry()
If mResult.gHasCarry Then mResult.LeftMakeUpUnits( 1 )
Return mResult
End Function
Private Sub RightMakeUpUnitsWhenMultiply( ByVal b As MathsUnit, ByVal indexOfMathunitFromLast As Integer )
Me .gLocalIndex += indexOfMathunitFromLast
End Sub
End Class
<
Serializable()
>
_
Public Class StringUnit
Private gValue As String = " 0 "
Private gLocalIndex As Integer = 0
Sub New ( ByVal value As String , ByVal localIndex As Integer )
gValue = value
gLocalIndex = localIndex
End Sub
Public ReadOnly Property Value() As String
Get
Return gValue
End Get
End Property
Public ReadOnly Property LocalIndex() As Integer
Get
Return gLocalIndex
End Get
End Property
End Class
Public Class StringUnit
Private gValue As String = " 0 "
Private gLocalIndex As Integer = 0
Sub New ( ByVal value As String , ByVal localIndex As Integer )
gValue = value
gLocalIndex = localIndex
End Sub
Public ReadOnly Property Value() As String
Get
Return gValue
End Get
End Property
Public ReadOnly Property LocalIndex() As Integer
Get
Return gLocalIndex
End Get
End Property
End Class