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
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
' 中间运算结果处理
< 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
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
' 进位处理
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
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
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
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
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