我能算到的阶乘有多大(五)

Author:水如烟 

贴在这看能看到不少错误。也方便随地能够看看想想。

运算单元做成这个样 :

< Serializable() >  _
Public   Class  MathUnit

    
Private  gOrignalValue  As   String   ' 原始值的字串表示
     Private  gCurrentValue  As   Object    ' 当前运算值

    
Private  gCurrentOperateResult  As   New  OperateResult  ' 中间运算结果

    
Private  gHasCarry  As   Boolean   =   False   ' 是否有进位
     Private  gCarry  As  MathUnit  ' 进位也是一个运算单元

    
Private  gIsFirstUnit  As   Boolean   =   False   ' 该单元是否是第一单元。由外部给出。控制输出结果字串。如果不是第一单元,需考虑补充位数。

    
' ----赋值----

    
Private   Sub  Initialize()
        gOrignalValue 
=   " 0 "
        gCurrentValue = Information.ConverToUnitDataType(0)


        gCurrentOperateResult.InputValue(
" 0 " )

        gHasCarry 
=   False
        gCarry 
=   Nothing
    
End Sub

    
Sub   New ()
        Initialize()
    
End Sub

    
Sub   New ( ByVal  isFirstUnit  As   Boolean )
        Initialize()
        gIsFirstUnit 
=  isFirstUnit
    
End Sub

    
Public   Sub  SetValue( ByVal  value  As   String )
        
' 不能大于单元位数
         If  value.Length  >  Information.UnitMaxSize  Then
            
Throw   New  Exception( String .Format(Information.MSG_UNIT_SIZE_OVERFLOW, Information.UnitMaxSize))
        
End   If

        Initialize()

        gOrignalValue 
=  value

        gCurrentValue 
=  Information.ConverToUnitDataType(value)

    
End Sub



    
' ----对外公布的信息----

    
Public   ReadOnly   Property  OrignalValue()  As   String
        
Get
            
Return  gOrignalValue
        
End   Get
    
End Property

    
Public   ReadOnly   Property  Value()  As   String
        
Get

            
Dim  mResult  As   String   =  gCurrentOperateResult.Value

            
If   Not  gIsFirstUnit  OrElse  gHasCarry  Then   ' 不是第一单元,或,是第一单元,但有进位
                mResult  =  Information.ConverToUnitDataTypeFullString(mResult)
            
End   If

            
Return  mResult
        
End   Get
    
End Property

    
Public   ReadOnly   Property  HasCarry()  As   Boolean
        
Get
            
Return  gHasCarry
        
End   Get
    
End Property


    
' ----一般函数----

    
Public   Function  Clone()  As  MathUnit
        
Return  CommonFunction.Clone( Of  MathUnit)( Me )
    
End Function

    
Public   Sub  CopyFrom( ByVal  unit  As  MathUnit)
        
With  unit
            gOrignalValue 
=  .gOrignalValue
            gCurrentValue 
=  .gCurrentValue

            gCurrentOperateResult.InputValue(.gCurrentOperateResult.OrignalValue)

            gHasCarry 
=  .gHasCarry
            gIsFirstUnit 
=  .gIsFirstUnit

            gCarry 
=  .gCarry.Clone
        
End   With

    
End Sub
End Class

 

 

Partial   Class  MathUnit

    
' 中间运算结果处理
     < Serializable() >  _
    
Private   Class  OperateResult

        
' 运算结果以字串形式传入
         Private  gInput  As   String   =   " 0 "

        
' 是否有进位
         Private  gHasCarry  As   Boolean   =   False
        
' 进位值字串
         Private  gCarry  As   String   =   " 0 "
        
' 值字串
         Private  gValue  As   String   =   " 0 "

        
Friend   ReadOnly   Property  OrignalValue()  As   String
            
Get
                
Return  gInput
            
End   Get
        
End Property

        
Friend   ReadOnly   Property  Value()  As   String
            
Get
                
Return  gValue
            
End   Get
        
End Property

        
Friend   ReadOnly   Property  Carry()  As   String
            
Get
                
Return  gCarry
            
End   Get
        
End Property

        
Friend   ReadOnly   Property  HasCarry()  As   Boolean
            
Get
                
Return  gHasCarry
            
End   Get
        
End Property

        
Public   Sub  InputValue( ByVal  value  As   String )
            gInput 
=  value
            Initialize()
        
End Sub

        
Private   Sub  Initialize()
            
Dim  mDigits  As   Integer   =  gInput.Length

            
If  mDigits  <=  Information.UnitMaxSize  Then
                gValue 
=  gInput
                gCarry 
=   " 0 "

                gHasCarry 
=   False
            
Else
                
Dim  mIndexSplit  As   Integer   =  mDigits  -  Information.UnitMaxSize

                gValue 
=  gInput.Substring(mIndexSplit)
                gCarry 
=  gInput.Substring( 0 , mIndexSplit)

                gHasCarry 
=   True
            
End   If
        
End Sub

    
End Class

End Class

 

Option   Strict   Off

Partial   Class  MathUnit

    
Public   Shared  Operator  = ( ByVal  a  As  MathUnit,  ByVal  b  As  MathUnit)  As   Boolean
        
Return  a.gCurrentValue  =  b.gCurrentValue
    
End  Operator

    
Public   Shared  Operator  <> ( ByVal  a  As  MathUnit,  ByVal  b  As  MathUnit)  As   Boolean
        
Return  a.gCurrentValue  <>  b.gCurrentValue
    
End  Operator

    
Public   Shared  Operator  > ( ByVal  a  As  MathUnit,  ByVal  b  As  MathUnit)  As   Boolean
        
Return  a.gCurrentValue  >  b.gCurrentValue
    
End  Operator

    
Public   Shared  Operator  >= ( ByVal  a  As  MathUnit,  ByVal  b  As  MathUnit)  As   Boolean
        
Return  a.gCurrentValue  >=  b.gCurrentValue
    
End  Operator

    
Public   Shared  Operator  < ( ByVal  a  As  MathUnit,  ByVal  b  As  MathUnit)  As   Boolean
        
Return  a.gCurrentValue  <  b.gCurrentValue
    
End  Operator

    
Public   Shared  Operator  <= ( ByVal  a  As  MathUnit,  ByVal  b  As  MathUnit)  As   Boolean
        
Return  a.gCurrentValue  <=  b.gCurrentValue
    
End  Operator

    
Public   Shared   Function  Max( ByVal  a  As  MathUnit,  ByVal  b  As  MathUnit)  As  MathUnit
        
If  a  >=  b  Then
            
Return  a
        
Else
            
Return  b
        
End   If
    
End Function

End Class

 

Partial   Class  MathUnit
    
' 进位处理

    
Private   Sub  ChekCarry()     ' 运算单元只保存一次进位。在累加或累乘过程中,若已存在进位,则需先处理进位,否则抛出异常

        
If  gHasCarry  Then
            
Throw   New  Exception(Information.MSG_UNIT_CARRY_OVERFLOW)
        
End   If
    
End Sub


    
Private   Sub  ChekCarryNeeded()  ' 检测是否需要进位

        gCurrentOperateResult.InputValue(gCurrentValue.ToString)

        
If   Not  gCurrentOperateResult.HasCarry  Then   Exit Sub

        gHasCarry 
=   True
        gCarry 
=   New  MathUnit(True)
        gCarry.SetValue(gCurrentOperateResult.Carry)
    
End Sub


    
Public   Sub  ReferCarryTo( ByRef  unit  As  MathUnit)  ' 向另一个运算单元提交进位
         If   Not   Me .HasCarry  Then   Exit Sub

        unit.Add(
Me .gCarry)

        
' 提交后
         Me .gCarry  =   Nothing

        
Me .gHasCarry  =   False

        
Me .gCurrentValue  =  Information.ConverToUnitDataType( Me .gCurrentOperateResult.Value)

    
End Sub

End Class

 

Option   Strict   Off

Partial   Class  MathUnit

    
Public   Sub  Add( ByVal  addend  As  MathUnit)
        
If  addend.gCurrentValue  =   0   Then   Exit Sub

        
Me .ChekCarry()

        
Me .gCurrentValue  +=  addend.gCurrentValue

        
Me .ChekCarryNeeded()

    
End Sub

    
Public   Shared  Operator  + ( ByVal  a  As  MathUnit,  ByVal  b  As  MathUnit)  As  MathUnit
        
Dim  c  As  MathUnit  =  a.Clone
        c.Add(b)
        
Return  c
    
End  Operator

End Class

 

Option   Strict   Off

Partial   Class  MathUnit

    
Public   Sub  Multy( ByVal  multyplier  As  MathUnit)
        
If  multyplier.gCurrentValue  =   0   Then
            
Me .Initialize()
            
Exit Sub
        
End   If

        
If   Me .gCurrentValue  =   0   Then   Exit Sub

        
Me .ChekCarry()

        
Me .gCurrentValue  *=  multyplier.gCurrentValue

        
Me .ChekCarryNeeded()

    
End Sub

    
Public   Shared  Operator  * ( ByVal  a  As  MathUnit,  ByVal  b  As  MathUnit)  As  MathUnit
        
Dim  c  As  MathUnit  =  a.Clone
        c.Multy(b)
        
Return  c
    
End  Operator

End Class

 

Public   Class  CommonFunction
    
Private   Sub   New ()
    
End Sub

    
Public   Shared   Function  Clone( Of  T)( ByVal  obj  As  T)  As  T
        
Dim  tmpT  As  T

        
Dim  mFormatter  As   New  System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
        
Dim  mMemoryStream  As   New  System.IO.MemoryStream

        
Using  mMemoryStream
            mFormatter.Serialize(mMemoryStream, obj)
            mMemoryStream.Position 
=   0
            tmpT 
=   CType (mFormatter.Deserialize(mMemoryStream), T)
            mMemoryStream.Close()
        
End   Using

        
Return  tmpT
    
End Function
End Class

 

Friend   Class  Information
    
Private   Sub   New ()
    
End Sub

    
Private   Shared  gUnitMaxSize  As   Integer
    
Private   Shared  gUnitDataType  As  TypeCode

    
' '' <summary>
     ' '' 运算单元最大位数
     ' '' </summary>
     Public   Shared   ReadOnly   Property  UnitMaxSize()  As   Integer
        
Get
            
Return  gUnitMaxSize
        
End   Get
    
End Property

    
' '' <summary>
     ' '' 运算单元数据类型
     ' '' </summary>
     ' '' <value></value>
     Public   Shared   ReadOnly   Property  UnitDataType()  As  TypeCode
        
Get
            
Return  gUnitDataType
        
End   Get
    
End Property

    
' '' <summary>
     ' '' 转换为运算单元数据类型
     ' '' </summary>
     ' '' <param name="Value">值</param>
     Public   Shared   Function  ConverToUnitDataType( ByVal  Value  As   Object As   Object
        
Return  System.Convert.ChangeType(Value, gUnitDataType)
    
End Function

    
Public   Shared   Function  ConverToUnitDataTypeFullString( ByVal  Value  As   Object As   String
        
Return  Value.ToString.PadLeft(gUnitMaxSize,  " 0 " c)
    
End Function


    
Shared   Sub   New ()

        
' 寻找可表示为整数的且表示范围最大的数据类型
         Dim  mTypeName  As   String
        
Dim  mType  As  Type
        
Dim  mFieldInfo  As  Reflection.FieldInfo


        
Dim  mMaxValue  As   String   =   " 0 "
        
Dim  mDataTypeCode  As  TypeCode

        
Dim  mCurrentTypeMaxValue  As   String   =   " 0 "
        
For   Each  c  As  TypeCode  In  [ Enum ].GetValues( GetType (TypeCode))

            mTypeName 
=  c.ToString
            mType 
=  Type.GetType( String .Format( " System.{0} " , mTypeName))

            mFieldInfo 
=  mType.GetField( " MaxValue " )
            
If  mFieldInfo  Is   Nothing   Then   Continue   For

            mCurrentTypeMaxValue 
=  mFieldInfo.GetValue( Nothing ).ToString

            
If   IsNumeric (mCurrentTypeMaxValue)  Then
                
If  mCurrentTypeMaxValue.Length  >  mMaxValue.Length  Then
                    mMaxValue 
=  mCurrentTypeMaxValue
                    mDataTypeCode 
=  c
                
End   If
            
End   If

        
Next

        gUnitDataType 
=  mDataTypeCode

        
' 确定该数据类型下,可表示的最大位数。保证两数相乘结果仍可表示为整数。
         Dim  x  As   Object
        x 
=  ConverToUnitDataType(mMaxValue)

        
Dim  mSqrtResult  As   String   =  Math.Sqrt( CDbl (x)).ToString  ' 最大数开方

        
Dim  mPointIndex  As   Integer   =  mSqrtResult.IndexOf( " . " c)  ' 只取整数部分
         If  mPointIndex  >   0   Then
            mSqrtResult 
=  mSqrtResult.Substring( 0 , mPointIndex)
        
End   If

        
Dim  mDigits  As   Integer   =  mSqrtResult.ToString.Length  -   1   ' 可表示的最大位数是最大数开方后整数部分位数减一位

        gUnitMaxSize 
=  mDigits
    
End Sub

    
Friend   Const  MSG_UNIT_SIZE_OVERFLOW  As   String   =   " 字串大于{0}位 "
    
Friend   Const  MSG_UNIT_CARRY_OVERFLOW  As   String   =   " 上次运算已有进位,不能再次运算 "
End Class
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值