本文介绍了.NET中的BigDecimal超过28位的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 限时删除!! 您好, 我需要一个BigDecimal-Class来计算超过28位的数字。 我试图使用W3bSine-Project并导入J#-BigDecimal-Type。 这两个方法都没有让我开心。原因W3bSine似乎有错误并且没有支持。 在.NET 4中有一个BigInteger - 但没有BigDecimal! 有谁知道一个很好的.NET库/类? 可以是商业的。 谢谢, Mike 解决方案 如果 BigDecimal 存在(并且可以创建这样的类型),它将不是真正的数字类型。术语十进制与数字以人类可读形式编写的形式有关,而与数值属性(如值,算术运算等)无关。这就是编程语言中不存在十进制类型的原因。然而,在这种类型中存在某种(小)意义:然后可以使用逐位数计算技术用作固定精度整数类型 - 就像传统的计算器一样。我认为这项技术已经走到了尽头。 如果你有 BigInteger - 你有你所需要的一切,只学会使用它。 目前尚不清楚,你想要整数还是小数。如果你需要一个固定精度的小数 - 这实际上是相同的 BigInteger ,但实现基于 BigInteger 需要一些认真的工作。原则上是可行的。 请在此处查看我的回答和讨论: 我想使用c#制作windows计算器,应该使用什么类型 [ ^ ]。 -SA 我写了这个BigInt的VB实现,我喜欢它,所以认为它可能会有所帮助。它无法处理真正巨大的数字,如格雷厄姆的数字,但它可以在大约3毫秒内计算普朗克长度(+/- 1)的宇宙体积,因此似乎适合大多数实际的大数字应用。它对加法,减法,乘法,积分除法,Log2和移位都是准确的。示例位于顶部,您可以随意以任何方式重复使用此代码。如果你喜欢它,并且你为Googol工作,请雇用我:) 公共结构BigInt 公共共享函数U()As BigInt'计划长度中的宇宙体积 Dim lRet As BigInt = New BigInt(10)^ 35'Planck-lengths per meter lRet =(lRet * 30000000)* 13700000 *(60 * 60 * 24 * 365)'可观察宇宙的直径在普朗克长度 lRet = BigInt.TimesPi((lRet ^ 3)* 4)\\ \\ 3'普朗克的宇宙体积 - 长度返回lRet 结束函数公共共享函数TimesPi(pBigInt As BigInt)As BigInt Dim lOp As BigInt '只是一个方便的理性近似Pi,十六进制为性能 Dim lSignificantDigits =(pBigInt.Log2 \ 4)+ 3 'lOp = BigInt.FromBase10(19018707285669230606090143944714770339621590768313546397192526115562704339680963564320007808107929370299752345187688835741387003036853 361285671158059867702399073227994426905220194699766118756059055619036488502928002591)'Debug.Print(Multiple =& BigInt.ToBase16(LOP)) LOP = BigInt.FromBase16(左( 5845B0A4C43FF041EE3CB64FE4AC283EC160121098D69A6E811E20511E3AE9B57DF4090D8855B3DC8BD649FA3756935283A0022779248D97ADD33C6B0BEAC74973DC124A3E1F0DBD6937F0E9E6975FF3C1C556B02A38ED94CE1F,lSignificantDigits))尺寸LRET作为BigInt有= pBigInt * LOP LOP = BigInt.FromBase10( 605384255146420326102361023215940531716391478150345020739231253172134740688232476946000058713774549796561447468267746412874022717544100946587144148739626803435133473281606663121381125761746030151344353855924025288111\" ) 'Debug.Print( 多路= &安培; BigInt.ToBase16(LOP)) LOP = BigInt.FromBase16(左( 1C1911716363228A62BB598F0ACD9C1565D39E10D84CE34459AF8E7B7C871CF668B48356882A8239FC1FD6523E3B273E5232C420D9CB5564A5A2D1E571BD2D4ED25995EB9B7B06A9721C4929034443808B4F399D6714F9F1E5AF,lSignificantDigits))' 调试.Print(Dividend =& BigInt.ToBase16(lOp)) lRet = lRet \ lOp 返回lRet 结束函数公共共享函数TestTimesPi(pReps As Integer)As Double Dim lOp As BigInt Dim lBigInt BigInt = U() Dim lEnd As Double Dim lRet As BigInt Dim lStart As Double = Microsoft.VisualBasic.Timer For i As Integer = 1 to pReps lRet = TimesPi(lBigInt) Next i lEnd = Microsoft.VisualBasic.Timer Debug.Print(lEnd - lStart& 秒为& pReps& pi计算)返回lEnd - lStart 结束函数私有mBytes作为列表(Byte)私有mIsNegative作为Boolean 公共函数IsEven()As Boolean 返回非IsOdd()结束函数公共函数IsOdd()As Boolean 如果IsZero()则返回False Else返回mBytes(0)和1 结束函数公共函数Abs()As BigInt Dim lRet As New BigInt lRet.mBytes = New List(Of Byte) lRet.mBytes.AddRange(mBytes) lRet.Normalize()返回lRet 结束函数 Public Sub Normalize()如果mBytes为Nothing那么 mIsNegative = False 退出Sub 结束如果如果mBytes.Count> 0然后而mBytes(mBytes.Count - 1)= 0 mBytes.RemoveAt(mBytes.Count - 1)结束时结束如果 If(mBytes .Count = 0)然后 mIsNegative = False 结束如果结束子公共子新(pVal为长)如果pVal< 0然后 mIsNegative = True pVal = -pVal 结束如果 mBytes =新列表(字节数)虽然pVal> 0 Dim lByte As Byte = pVal和255 mBytes.Add(lByte) pVal = pVal>> 8 结束时'无需规范化此结束子公共子新(pBigInt As BigInt) mBytes =新列表(字节数) mBytes.AddRange(pBigInt.mBytes.ToArray) mIsNegative = pBigInt.mIsNegative Normalize() End Sub 公共共享运算符 - (ByVal class1 As BigInt)As BigInt Dim lRet As New BigInt(class1) lRet.mIsNegative = Not lRet.mIsNegative lRet.Normalize()返回lRet 结束运算符公共共享函数比较(ByVal class1 As BigInt,ByVal class2 As BigInt)As Integer class1.Normalize() class2.Normalize() If class1.IsZero Then If class2.IsZero然后返回0 ElseIf class2.mIsNegative然后返回1 否则返回-1 结束如果 ElseIf class2。 IsZero然后如果class1.mIsNegative然后返回-1 否则返回1 结束如果 ElseIf class1.mIsNegative然后如果class2 .mIsNegative然后返回-Compare(-class1,-class2)否则返回-1 结束如果 ElseIf class2.mIsNegative然后返回1 结束如果'处理正阳性比较这里 Dim iLeft As Integer = class1.mBytes.Count - 1 Dim iRight As Integer = class2.mBytes.Count - 1 虽然iLeft> iRight 如果class1.mBytes(iLeft)<> 0然后返回1 结束如果 iLeft - = 1 结束时虽然iRight> iLeft 如果class2.mBytes(iRight)<> 0然后返回-1 结束如果 iRight - = 1 结束时虽然iLeft> = 0 如果class1.mBytes(iLeft) < class2.mBytes(iLeft)然后返回-1 ElseIf class1.mBytes(iLeft)> class2.mBytes(iLeft)然后返回1 结束如果 iLeft - = 1 结束时返回0 结束函数公开共享运算符<(ByVal class1 As BigInt,ByVal class2 As BigInt)As Boolean Select Case Compare(class1,class2) Case -1 返回True Case Else 返回False 结束选择结束运算符公共共享运算符>(ByVal class1 As BigInt,ByVal class2 As BigInt)As Boolean Select Case Compare(class1,class2) 案例1 返回True 案例Else 返回False 结束选择结束运算符公共共享运算符< =(ByVal class1 As BigInt,ByVal class2 As BigInt)As Boolean Select Case Compare(class1,class2) Case 0,-1 返回True Case Else 返回False 结束选择结束运算符公共共享运算符> =(ByVal class1 As BigInt,ByVal class2 As BigInt)As Boolean 选择案例比较(class1,class2)案例0,1 返回True 案例Else 返回False 结束选择结束运算符公共共享运算符=(ByVal class1 As BigInt,ByVal class2 As BigInt)As Boolean Select Case Compare(class1,class2) Case 0 返回True Case Else 返回False 结束选择结束运算符公共共享运算符<>(ByVal class1 As BigInt,ByVal class2 As BigInt)As Boolean Select Case Compare(class1, class2) Case 0 返回False Case Else 返回True 结束选择结束运算符公共函数IsZero()As Boolean 如果mBytes为Nothing则返回True 如果mBytes.Count = 0则返回True For Each lByte以mBytes 如果lByte<> 0然后返回False 下一个返回True 结束函数公共共享运算符+(ByVal class1 As BigInt,ByVal class2 As Long)As BigInt 返回class1 + New BigInt(class2)结束运算符公共共享运算符+(ByVal class1 As BigInt,ByVal class2 As BigInt)As BigInt 如果class1.mBytes Is Nothing则返回class2 如果class2 .mBytes Is Nothing Then返回class1 Dim lBytes1 As Integer = class1.mBytes.Count Dim lBytes2 As Integer = class2.mBytes.Count Dim lBytes As New List(Of Byte) Dim lRemainder As Byte = 0 Dim i As Integer = 0 Dim lZeros As Integer = 0 While(i< lBytes1)Or(i< lBytes2)Or(l< lBytes2)Or(lRemainder< ;> 0) Dim lByte1 As Integer = 0 Dim lByte2 As Integer = 0 Dim lTemp As Integer = 0 如果i< lBytes1然后lByte1 = class1.mBytes(i)如果i< lBytes2然后lByte2 = class2.mBytes(i) lTemp = lByte1 + lByte2 + lRemainder lRemainder = 0 如果lTemp> 255然后 lRemainder = lTemp \ 256 lTemp - = 256 * lRemainder 结束如果 lBytes.Add(lTemp)如果lTemp = 0那么lZeros + = 1 Else lZeros = 0 i + = 1 结束时虽然lZeros> 0 lBytes.RemoveAt(lBytes.Count - 1) lZeros - = 1 结束时 Dim lRet As New BigInt lRet.mBytes = lBytes 返回lRet 结束运算符公共共享运算符 - (ByVal class1 As BigInt,ByVal class2 As Long)As BigInt 返回class1 - 新BigInt(class2)结束运算符公共共享的运营商 - (BYVAL class1的作为BigInt有,BYVAL Class2中作为BigInt有)作为BigInt有尺寸lResultIsNegative作为布尔值尺寸lLeft作为BigInt有尺寸lRight作为BigInt有 class1.Normalize () class2.Normalize()如果class1.mIsNegative那么如果class2.mIsNegative那么返回 - (class1.Abs + class2.Abs)否则返回class1.Abs + class2 结束如果 ElseIf class2.mIsNegative然后返回class1 + class2.Abs 结束如果 Select Case Compare(class1,class2) Case 0 返回New BigInt(0) Case -1 lResultIsNegative = True lLeft = class2 lRight = class1 Case 1 lResultIsNegative = False lLeft = class1 lRight = class2 Case Else 抛出新的InvalidOperationException(BigInt.vb遇到无效比较数字时的结果。)结束选择 '左边大于右边,如果指示 Dim lBorrow As Integer = 0 Dim lRet As New BigInt(0) For i As Integer = 0 to lLeft.mBytes.Count - 1 Dim iLeft As Integer Dim iRight As Byte iLeft = lLeft.mBytes (i) - lBorrow 如果i> = lRight.mBytes.Count那么 iRight = 0 否则 iRight = lRight.mBytes(i)结束如果 lBorrow = 0 虽然iLeft< iRight lBorrow + = 1 iLeft + = 256 End lRet.mBytes.Add(iLeft - iRight) Next lRet.mIsNegative = lResultIsNegative lRet.Normalize()返回LRET 结束操作公共共享功能GrahamNotation(PBASE为整数,pArrows作为整数,pHeight作为整数)作为BigInt有返回GrahamNotation(新BigInt有(PBASE),pArrows,新BigInt有(pHeight))端功能公共共享功能GrahamNotation(PBASE作为BigInt有,pArrows作为整数,pHeight作为BigInt有)作为BigInt有。如果pArrows> 1然后返回GrahamNotation(pBase,pArrows - 1,GrahamNotation(pBase,1,pHeight))结束如果 Dim lRet As BigInt = pBase lRet = pBase ^ pHeight 'lRet = lRet ^(pHeight - 1)返回lRet 结束函数公共共享运算符*(ByVal class1 As BigInt,pByte As Byte)As BigInt Dim lBytes1 As Integer = class1.mBytes.Count Dim lOutBytes As New List(Of Byte) Dim lCarry As Long = 0 For i = 0 To lBytes1 - 1 Dim lTemp As Long =(CLng(class1.mBytes(i))* pByte)+ lCarry lCarry = 0 如果lTemp> 255然后 lCarry = lTemp \ 256 lTemp = lTemp Mod 256 结束如果 lOutBytes.Add(CByte(lTemp))下一个'而lCarry> 255 如果lCarry> 255然后 lOutBytes.Add(CByte(lCarry Mod 256)) lCarry = lCarry \ 256 结束如果'结束而如果lCarry> 0然后lOutBytes.Add(CByte(lCarry)) Dim lRet As New BigInt lRet.mBytes = lOutBytes lRet.mIsNegative = class1.mIsNegative 返回lRet 结束运算符公共共享运算符^(ByVal class1 As BigInt,class2 As BigInt)As BigInt class2.Normalize() If class2.IsZero Then Return New BigInt(1)如果class2 = New BigInt(1)那么返回class1 Dim lIsNegative As Boolean = False 如果class1.mIsNegative AndAlso(class2.mBytes(0)和1)那么lIsNegative = True Dim lPow作为New BigInt(class2) Dim lBase As New BigInt(class1) Dim l1 As New BigInt(1) Dim lSuperpow As New BigInt(l1) Dim lMultiplier As New BigInt(l1) Dim l2 As New BigInt(2)而lPow> l2 如果lPow.IsOdd那么 lPow - = l1 lMultiplier = lMultiplier *(lBase ^ lSuperpow) Else lPow = lPow>> 1 lSuperpow = lSuperpow<< 1 结束如果结束而 lBase = lBase ^ lSuperpow 如果lPow = l2那么lMultiplier = lMultiplier * lBase lBase = lBase * lMultiplier '如果lSuperpow> l1然后lBase = lBase ^ lSuperpow 返回lBase 结束运算符 公共共享运算符^(ByVal class1 As BigInt,class2 As Integer)As BigInt 返回class1 ^新BigInt(class2)结束运营商公共共享运营商*(ByVal class1 As BigInt,class2 As Long)As BigInt 返回class1 * New BigInt(class2) End Operator 公共共享运营商*(ByVal class1 As BigInt,class2 As BigInt)As BigInt Dim lTop As BigInt Dim lBottom As BigInt class1.Normalize() class2.Normalize()如果class1.IsZero或class2.IsZero然后返回New BigInt(0) Dim lResultIsNegative As Boolean = class1.mIsNegative Xor class2.mIsNegative If class1.mBytes .Count< class2.mBytes.Count然后 lTop = class2 lBottom = class1 否则 lTop = class1 lBottom = class2 结束如果 Dim lRunningTotal As New BigInt For i = 0 To lBottom.mBytes.Count - 1 Dim lAdditive As BigInt = lTop * CByte(lBottom.mBytes(i)) for j = 1至I lAdditive.mBytes.Insert(0,CByte(0))下一 lRunningTotal + = lAdditive 下一 lRunningTotal.mIsNegative = lResultIsNegative lRunningTotal.Normalize()返回lRunningTotal 结束运算符公共共享函数PowerOf2(pPower As Integer)As BigInt Dim lRet As BigInt = New BigInt(1)< < (pPower - 1)返回lRet 结束函数私有共享mPowersOf10 As Dictionary(Of Integer,BigInt) 公共共享函数ClearCachedPowers()如果mPowersOf10 IsNot Nothing那么 mPowersOf10.Clear()结束如果结束函数公共共享函数PowerOf10(pPower As Integer)As BigInt 如果pPower = 0那么返回New BigInt(1) ElseIf pPower = 1然后返回New BigInt(10) ElseIf mPowersOf10.ContainsKey(pPower)然后返回New BigInt(mPowersOf10 (pPower)) Else mPowersOf10(pPower)= New BigInt(10)^ pPower 返回New BigInt(mPowersOf10(pPower))结束如果结束函数公共共享运营商\(ByVal class1 As BigInt,class2 As BigInt)As BigInt Dim lResult As BigInt = New BigInt(0) Divide(class1,class2, lResult,New BigInt(0))返回lResult 结束运算符公共共享运算符/(ByVal class1 As BigInt,class2 As Long)As BigDecimal1 'Dim lResult As BigDecimal =新BigInt(0)'除以(class1,New BigInt(class2),lResult,New BigInt(0))'返回lResult 结束运营商公共共享运营商/( ByVal class1 As BigInt,class2 As BigInt)As BigDecimal1 'Dim lResult As BigInt = New BigInt(0)'Divide(class1,New BigInt(class2),lResult,New BigInt(0))'返回lResult 结束运算符公共共享运算符\(ByVal class1 As BigInt,class2 As Long)As BigInt Dim lResult As BigInt = New BigInt(0)除以(class1,New BigInt(class2),lResult,New BigInt(0))返回lResult 结束运算符公共共享运算符Mod(ByVal class1 As BigInt,class2 As BigInt)As BigInt Dim lResult As BigInt = New BigInt(0)除以(class1,class2,New BigInt(0),lResult)返回lResult 结束运算符公共共享运算符Mod(ByVal class1 As BigInt ,class2 As Long)As BigInt Dim lResult BigInt = New BigInt(0)除以(class1,New BigInt(class2),New BigInt(0),lResult)返回lResult 结束运算符公共函数ToByte()As Byte Normalize()如果IsZero()则返回0 返回mBytes(0)结束函数 Public Shared Sub SquareTest(pPower As Integer) Dim lRet As BigInt =(New BigInt(1)<< pPower) - New BigInt(1) Debug.Print(lRet.ToString) End Sub Public Shared Sub SpeedTest2() Dim lBigNum作为BigInt = New BigInt(10) Dim lTime1 As Double = Microsoft.VisualBasic.Timer lBigNum = lBigNum ^ 1000 Dim lTime2 As Double = Microsoft.VisualBasic.Timer Debug .Print((lTime2 - lTime1)&秒来计算Googol ^ 10) lTime1 = Microsoft.VisualBasic.Timer lBigNum = lBigNum ^ 50 lTime2 = Microsoft.VisualBasic.Timer Debug.Print((lTime2 - lTime1)&秒将其提升到50次幂) Debug.Print(结果是& lBigNum.Log2&位长。 ) Debug.Print(转换为十进制......) lTime1 = Microsoft.VisualBasic.Timer Debug.Print(lBigNum.ToString) lTime2 = Microsoft。 VisualBasic.Timer Debug.Print(转换为十进制&am磷; (lTime2 - lTime1)& 秒。)结束Sub 公共共享Sub SpeedTest3() Debug.Print(生成3(箭头)3) Dim lTime1 As Double = Microsoft.VisualBasic .Timer Dim lBigInt = BigInt.GrahamNotation(3,1,3) Dim lTime2 As Double = Microsoft.VisualBasic.Timer Debug.Print(Time elapsed:&(lTime2 - lTime1)) Debug.Print(lBigInt.ToString) Debug.Print(Generating 3(double-arrow)3) lTime1 = Microsoft.VisualBasic.Timer lBigInt = BigInt.GrahamNotation(3,2,3) lTime2 = Microsoft.VisualBasic.Timer Debug.Print(Time elapsed:&(lTime2 - lTime1)) Debug.Print(lBigInt.ToString) 退出Sub Debug.Print(lBigInt.mBytes.Count&bytes) Debug.Print (生成3(三箭头)2) lTime1 = Microsoft.VisualBasic.Timer lBigInt = BigInt.GrahamNotation(3,3, 2) lTime2 = Microsoft.VisualBasic.Timer Debug.Print(Time elapsed:& (lTime2 - lTime1)) Debug.Print(lBigInt.ToString) Debug.Print(lBigInt.mBytes.Count&bytes) Debug.Print(Generating 3(triple) -arrow)3) lTime1 = Microsoft.VisualBasic.Timer lBigInt = BigInt.GrahamNotation(3,3,3) lTime2 = Microsoft.VisualBasic.Timer Debug。打印(已过去的时间:&(lTime2 - lTime1)) Debug.Print(lBigInt.ToString) Debug.Print(lBigInt.mBytes.Count&bytes) End Sub Public Shared Sub SpeedTest4() Dim lBigInt As BigInt = GrahamNotation(2,4,2) Debug.Print(lBigInt.ToString) End Sub 公共共享Sub SpeedTest() Dim lTime1 As Double = Microsoft.VisualBasic.Timer Dim j As Integer For i = 1 To 1000000 j = j + 1 下一个 Dim lTime2 As Double = Microsoft.VisualBasic.Timer Debug.Print(整数:& (lTime2 - lTime1)) Dim k As New BigInt(0) Dim l1 As New BigInt(1) For i = 1 To 10000 k = k + l1 下一个 lTime1 = Microsoft.VisualBasic.Timer Debug.Print(BigInt:&(lTime1 - lTime2)) End Sub 公共函数ToInt16()As Int16 Dim lRet As Int16 If IsZero()然后返回0 如果mBytes.Count> 1然后lRet = lRet +(CLng(mBytes(1)和127)<< 8)如果mBytes.Count> 0然后lRet = lRet + mBytes(0)如果mIsNegative然后返回-lRet Else返回lRet 结束函数公共函数ToInt32()As Int32 Dim lRet As Int32 如果IsZero()则返回0 如果mBytes.Count> 3然后lRet = lRet +(CLng(mBytes(3)和127)<< 24)如果mBytes.Count> 2然后lRet = lRet +(CLng(mBytes(2))<< 16)如果mBytes.Count> 1然后lRet = lRet +(CLng(mBytes(1))<< 8)如果mBytes.Count> 0然后lRet = lRet + mBytes(0)如果mIsNegative然后返回-lRet Else返回lRet 结束函数 私有共享子除(pDividend作为BigInt,pDivisor作为BigInt, ByRef pResult As BigInt,ByRef pModulus As BigInt) pDivisor.Normalize()如果pDivisor.IsZero然后抛出新DivideByZeroException pDividend.Normalize()如果pDividend.IsZero那么 pResult = New BigInt(0) pModulus = New BigInt(0)退出Sub 结束如果 Dim lResultIsNegative As Boolean = pDividend.mIsNegative Xor pDivisor.mIsNegative Dim lDividend As BigInt = pDividend.Abs Dim lDivisor As BigInt = pDivisor.Abs Select Case Compare(lDividend,lDivisor) Case -1 pResult = New BigInt (0) pModulus =新BigInt(lDividend)退出Sub 案例0 pResult = New BigInt(1) pModulus = New BigInt(0)退出Sub 结束选择'红利大于除数'将红利乘以256而 Dim lShift As Integer Dim lRunningTotal As New BigInt(0)而不是lDividend.IsZero 如果lDividend< lDivisor然后 pModulus = lDividend pResult = lRunningTotal 退出小组结束如果 LSHIFT = Math.Truncate(lDividend.Log2_Dbl - lDivisor.Log2_Dbl) 'lShift = Math.Truncate(lDividend.Log2 - lDivisor.Log2) Dim lTestDivisor As BigInt = lDivisor<< lShift 如果lTestDivisor> lDividend然后 lTestDivisor = lTestDivisor>> 1 lShift - = 1 结束如果 lRunningTotal + =(New BigInt(1)<< lShift) lDividend - = lTestDivisor 结束时 pResult = lRunningTotal pModulus = New BigInt(0)退出Sub End Sub 公共共享运营商<< ;(pBigInt As BigInt,pBits As Integer)As BigInt Dim lRet As New BigInt(pBigInt) Dim lBits As Integer = pBits pBigInt.Normalize() if lBits> ; = 8然后 Dim lInsertBytes((pBits \ 8) - 1)As Byte lRet.mBytes.InsertRange(0,lInsertBytes) lBits = lBits Mod 8 End如果如果lBits = 0那么 lRet.Normalize()返回lRet 结束如果 Dim lMostSignificantBit As Byte = Log2(lRet.mBytes(lRet.mBytes。计数 - 1)) Dim lAvailableBits As Byte = 8 - lMostSi gnificantBit 如果lAvailableBits< lBits然后lRet.mBytes.Add(0) Dim lMaskLeft As Byte =(1<<(lBits + 1)) - 1 Dim lMaskRight As Byte = Not lMaskLeft For i = 1Ret.mBytes.Count - 1到1步-1 lRet.mBytes(i)=((1Ret.mBytes(i)<< lBits)或(lRet.mBytes(i-1)> >(8 - lBits)))和255 下一个 lRet.mBytes(0)=(lRet.mBytes(0)<< lBits)和255 返回lRet 结束运算符公共共享运算符>>(pBigInt作为BigInt,pBits作为整数)作为BigInt Dim lRet作为新BigInt(pBigInt) Dim lBits As Integer = pBits pBigInt.Normalize()如果lBits> = 8那么 lRet.mBytes.RemoveRange(0,pBits = 8) lBits = lBits Mod 8 结束如果如果lBits = 0那么 lRet.Normalize()返回lRet 结束如果 Dim lMostSignificantBit As Byte = Log2(lRet.mBytes(l Ret.mBytes.Count - 1)) Dim lAvailableBits As Byte = 8 - lMostSignificantBit 如果lAvailableBits< lBits然后lRet.mBytes.Add(0) Dim lMaskLeft As Byte =(1<<(lBits + 1)) - 1 Dim lMaskRight As Byte = Not lMaskLeft For i = 0到lRet.mBytes.Count - 2 lRet.mBytes(i)=((lRet.mBytes(i)>> lBits)或(lRet.mBytes(i + 1)<<( 8 - lBits))) And 255 Next lRet.mBytes(lRet.mBytes.Count - 1) = (lRet.mBytes(lRet.mBytes.Count - 1) >> lBits) And 255 Return lRet End Operator Public Function Log2() As Long Normalize() If IsZero() Then Return 0 Return ((mBytes.Count - 1) * 8) + Log2(mBytes(mBytes.Count - 1)) End Function Public Function Log2_Dbl() As Double Normalize () If IsZero() Then Return 0 Dim lBits As Integer = (mBytes.Count - 1) * 8 Dim lDivisor As Double = 1 Dim lRunningTotal As Double = lBits + Log2_Dbl(mBytes(mBytes.Count - 1 )) For i = mBytes.Count - 2 To Math.Max(mBytes.Count - 8, 0) Step -1 lDivisor = lDivisor * 256 lRunningTotal += (CDbl(Log2_Dbl(mBytes(i))) / lDivisor) Next Return lRunningTotal End Function Public Overrides Function ToString() As String Return BigInt.ToBase10(Me) End Function Public Shared Function ToBaseX(pBigInt As BigInt, pBase As Byte) As String If pBase < 2 Then Throw New ArgumentException(\"Cannot display as base less than 2\") If pBase > 2 Then Throw New ArgumentException(\"Cannot display as base greater than 16\") pBigInt.Normalize() If pBigInt.IsZero Then Return \"0\" Dim aChars() As Char = {\"0\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\", \"A\", \"B\", \"C\", \"D\", \"E\", \"F\"} Dim lRet As New System.Text.StringBuilder() If pBigInt.mIsNegative Then lRet.Append(\"-\") lRet.Append(\"&(\" & pBase & \")\") Dim lByte As Byte = (pBigInt Mod pBase).ToByte If lByte And &HF0 Then lRet.Append(aChars(lByte)) End If If lByte And &HF Then lRet.Append(aChars(lByte And &HF)) End If For i = pBigInt.mBytes.Count - 2 To 0 Step -1 lByte = pBigInt.mBytes(i) lRet.Append(aChars(lByte >> 4) & aChars(lByte And 15)) Next Return lRet.ToString End Function Public Shared Function ToBase16(pBigInt As BigInt) As String pBigInt.Normalize() If pBigInt.IsZero Then Return \"0\" Dim aChars() As Char = {\"0\", \"1\", \"2\", \"3\", \"4\", \"5\", \"6\", \"7\", \"8\", \"9\", \"A\", \"B\", \"C\", \"D\", \"E\", \"F\"} Dim lRet As New System.Text.StringBuilder() If pBigInt.mIsNegative Then lRet.Append(\"-\") lRet.Append(\"&H\") Dim lByte As Byte = pBigInt.mBytes(pBigInt.mBytes.Count - 1) If lByte And &HF0 Then lRet.Append(aChars(lByte >> 4)) End If If lByte And &HF Then lRet.Append(aChars(lByte And &HF)) End If For i = pBigInt.mBytes.Count - 2 To 0 Step -1 lByte = pBigInt.mBytes(i) lRet.Append(aChars(lByte >> 4) & aChars(lByte And 15)) Next Return lRet.ToString End Function Public Function ToBase16() As String Return BigInt.ToBase16(Me) End Function Public Shared Function FromBase10(pSource As String) As BigInt Dim lMode As Byte = 1 Dim lIsNegative As Boolean Dim lNB As New System.Text.StringBuilder Dim lDec As Integer = -1 Dim lShiftDirection As Char Dim lShiftAmt As String For Each lChar In pSource Select Case lMode Case 1 Select Case lChar Case \" \", \"+\" Case \"-\" lIsNegative = True lMode = 2 Case \"0\" ’ignore leading zeros Case \"1\" To \"9\" lNB.Append(lChar) lMode = 2 Case \".\" lDec = lNB.Length lMode = 3 Case Else Throw New InvalidCastException End Select Case 2 Select Case lChar Case \",\" Case \"0\" To \"9\" lNB.Append(lChar) Case \".\" lDec = lNB.Length lMode = 3 Case \"E\" lMode = 4 Case Else Throw New InvalidCastException End Select Case 3 Select Case lChar Case \",\" Case \"0\" To \"9\" lNB.Append(lChar) Case \"E\" lMode = 4 lShiftDirection = \"+\" Case Else Throw New InvalidCastException End Select Case 4 Select Case lChar Case \"+\", \"-\" lShiftDirection = lChar lM ode = 5 Case \"0\" Case \"1\" To \"9\" lShiftAmt = lShiftAmt & lChar lMode = 6 Case Else Throw New InvalidCastException End Select Case 5 Select Case lChar Case \"0\" Case \"1\" To \"9\" lShiftAmt = lShiftAmt & lChar lMode = 6 Case Else Throw New InvalidCastException End Select Case 6 Select Case lChar Case \"0\" To \"9\" lShiftAmt = lShiftAmt & lChar lMode = 6 Case Else Throw New InvalidCastException End Select End Select Next If lDec = -1 Then lDec = lNB.Length + 1 Dim lAsDecimal As String If lShiftAmt = \"\" Then lAsDecimal = lNB.ToString ElseIf lShiftDirection = \"+\" Then lDec = lDec + Val(lShiftAmt) If lDec > (lNB.Length + 1) Then lAsDecimal = lNB.ToString & New String(\"0\", (lDec - lNB.Length) - 1) Else lAsDecimal = lNB.ToString.Substring(0, lDec - 1) End If ElseIf lShiftDirection = \"-\" Then lDec = lDec - Val(lShiftAmt) If lDec < 1 Then Return New BigInt(0) Else lAsDecimal = lNB.ToString.Substring(0, lDec - 1) End If End If ’lAsDecimal is now a clean, unsigned decimal with scientific notation expanded Dim l10 As BigInt = New BigInt(10) Dim lTens As BigInt = New BigInt(1) Dim lRet As BigInt = New BigInt(0) For i = lAsDecimal.Length - 1 To 0 Step -1 Dim lAdditive As BigInt = lTens * New BigInt(Asc(lAsDecimal.Substring(i, 1)) - 48) lRet += lAdditive lTens = lTens * l10 Next lRet.mIsNegative = lIsNegative lRet.Normalize() Return lRet End Function Public Shared Function FromBase16(pSource As String) As BigInt Dim lProc As New Stack(Of Byte) Dim lTemp As String = \"\" Dim lRet As New BigInt(0) $b$ b For i = 0 To pSource.Length - 1 Dim lChar As Char = pSource.Substring(i, 1) Dim lAsc As Integer = Asc(lChar) Select Case lAsc Case 48 To 57 lTemp = lTemp & lChar Case 65 To 70 lTemp = lTemp & lChar End Select If Len(lTemp) = 2 Then Dim lByte As Byte = 0 lAsc = Asc(lTemp.Substring(0, 1)) Select Case lAsc Case 48 To 57 lByte = (lAsc - 48) << 4 Case 65 To 70 lByte = (lAsc - 55) << 4 End Select lAsc = Asc(lTemp.Substring(1, 1)) Select Case lAsc Case 48 To 57 lByte = lByte + (lAsc - 48) Case 65 To 70 lByte = lByte + (lAsc - 55) End Select lTemp = \"\" lRet.mBytes.Insert(0, lByte) End If Next If lTemp <> \"\" Then Select Case Asc(lTemp) Case 48 To 57 lRet = lRet << 4 lRet += New BigInt(Asc(lTemp) - 48) Case 65 To 70 lRet = lRet << 4 lRet += New BigInt(Asc(lTemp) - 55) End Select End If lRet.Normalize() Return lRet End Function Public Shared Function ToBase10(pBigInt As BigInt) As String Dim lRemaining As BigInt = pBigInt Dim lStack As New Stack(Of Char) Dim lMod As BigInt = Nothing Dim lDigit As Byte Dim l10 As New BigInt(10) Dim l10K As New BigInt(10000) Dim l1B As New BigInt(1000000000) Dim l1Googol As BigInt = New BigInt(0) If pBigInt.Log2 >= 332 Then l1Googol = New BigInt(10000) ^ 25 Dim l1GoogolE10 As BigInt = New BigInt(0) If pBigInt.Log2 >= 3321 Then l1GoogolE10 = l1Googol ^ 10 pBigInt.Normalize() If pBigInt.IsZero Then Return \"0\" Dim lLastUpdate As Double = Microsoft.VisualBasic.Timer Dim lStartTime As D ateTime = Now Dim lStartDigits As Integer = lRemaining.Log2 Dim lStackSize As Long = 0 Do If (Not l1GoogolE10.IsZero) AndAlso (lRemaining > l1GoogolE10) Then Divide(lRemaining, l1GoogolE10, lRemaining, lMod) Dim lText As String = lMod.ToString.PadLeft(1000, \"0\") For i = lText.Length - 1 To 0 Step -1 lStack.Push(lText.Substring(i, 1)) Next lStackSize += lText.Length ElseIf (Not l1Googol.IsZero) AndAlso (lRemaining > l1Googol) Then Divide(lRemaining, l1Googol, lRemaining, lMod) Dim lText As String = lMod.ToString.PadLeft(100, \"0\") For i = lText.Length - 1 To 0 Step -1 lStack.Push(lText.Substring(i, 1)) Next lStackSize += lText.Length ElseIf lRemaining > l1B Then Divide(lRemaining, l1B, lRemaining, lMod) Dim lText As String = Format(lMod.ToInt32, \"000000000\") For i = lText.Length - 1 To 0 Step -1 lStack.Push(lText.Substring(i, 1)) Next lStackSize += lText.Length ElseIf lRemaining > l10K Then Divide(lRemaining, l10K, lRemaining, lMod) Dim lText As String = Format(lMod.ToInt16, \"0000\") For i = lText.Length - 1 To 0 Step -1 lStack.Push(lText.Substring(i, 1)) Next lStackSize += lText.Length Else Divide(lRemaining, l10, lRemaining, lMod) lStack.Push(CStr(lMod.ToByte)) lStackSize += 1 End If If (Microsoft.VisualBasic.Timer - lLastUpdate) > 10 Then Dim lLog2 As Integer = lRemaining.Log2 If lLog2 < lStartDigits Then Debug.Print(lLog2 & \" significant digits remaining.\") Dim lTimeSpent As TimeSpan = Now.Subtract(lStartTime) Dim lUnitTime As Double = lTimeSpent.TotalSeconds / (lStartDigits - lLog2) Dim lCompletion As DateTime = Now.AddSeconds(lUnitTime * lLog2 * (lLog2 / lStartDigits) / 3) Debug.Print(\"Estimated Completion: \" & Format(lCompletion, \"M/d/yyyy HH:mm:ss\")) Dim lDigitRatio As Double = lStackSize / (lStartDigits - lLog2) Debug.Print(\"Estimated Output Digits: \" & (lStackSize + CInt(lDigitRatio * lLog2))) lLastUpdate = Microsoft.VisualBasic.Timer End If End If Loop Until lRemaining.IsZero If pBigInt.mIsNegative Then lStack.Push(\"-\") Dim lRet As New System.Text.StringBuilder Whi le lStack.Count lRet.Append(lStack.Pop) End While If Now - lStartTime > New TimeSpan(0, 1, 0) Then Using lwriter As New IO.StreamWriter(\"c:\temp\Calculation.txt\", False) lwriter.WriteLine(lRet.ToString) lwriter.Close() lwriter.Dispose() End Using End If Return lRet.ToString End Function Public Shared Function Log2(pByte As Byte) As Byte Dim lRet As Byte While pByte <> 0 lRet += 1 pByte = pByte >> 1 End While Return lRet End Function Public Shared Function Log2(pInteger As Integer) As Byte Dim lRet As Byte If pInteger < 0 Then Throw New InvalidOperationException(\"BigInt cannot take the logarithm of a negative number.\") While pInteger <> 0 lRet += 1 pInteger = pInteger >> 1 End While Return lRet End Function Public Shared Function Log2_Dbl(pByte As Byte) As Double Dim lRet As Double = 8 If pByte = 0 Then Return 0 While (pByte And &H80) = 0 lRet -= 1 pByte = pByte << 1 End While pByte = pByte << 1 Dim lDivisor As Integer = 2 While pByte <> 0 If pByte And &H80 Then lRet = lRet + 1 / lDivisor End If lDivisor *= 2 pByte = pByte << 1 End While Return lRet End Function Public Shared Function Log2_Dbl(pInteger As Integer) As Double Dim lRet As Double = 8 If pInteger = 0 Then Return 0 While (pInteger And &H8000) = 0 lRet -= 1 pInteger = pInteger << 1 End While pInteger = pInteger << 1 Dim lDivisor As Integer = 2 While pInteger <> 0 If pInteger And &H8000 Then lRet = lRet + 1 / lDivisor End If lDivisor *= 2 pInteger = pInteger << 1 End While Return lRet End Function End StructureHello,I need a BigDecimal-Class for calculating with numbers with more than 28 digits.I tried to use the W3bSine-Project and to import the J#-BigDecimal-Type.Both approched didn't make me happy. Cause W3bSine seems to be buggy and there is no support.In .NET 4 there is a BigInteger - but no BigDecimal!Does anyone knows a good Library / Class for .NET?Could be comercial.Thanks,Mike 解决方案 If BigDecimal existed (and it is possible to create such type), it would not be a real numeric type. The term "decimal" is related to the form a numeric is written in human readable form, not to the numeric properties like value, arithmetic operations, etc. That's why such things as "decimal" types do not exist in programming languages. Nevertheless, there is certain (little) sense in such type: then could be used as fixed-precision integer type using the technology of calculation "digit-by-digit" — like in traditional calculators. I think this technology is rendered a dead end.If you have BigInteger — you have all you need, only learn to use it.It is not clear, do you want integer or fractional number. If you need a fixed-precision fractional — this is practically the same is BigInteger, but implementing floating-point based on BigInteger will need some serious work. Is is in principle possible.Please see my past Answer and discussion here:I would like to use c # to make the windows calculator, what type should be used[^].—SAI wrote this VB implementation of BigInt, and I like it, so thought it might be helpful. It can't handle truly gigantic numbers like graham's number, but it can calculate the volume of the universe in planck-lengths (+/- 1) in about 3 milliseconds, and thus seems suitable for most practical big-number applications. It's accurate for addition, subtraction, multiplication, integral division, Log2, and Shifting. Examples are at the top, feel free to reuse this code in any way you please. If you like it, and you work for Googol, hire me :)Public Structure BigInt Public Shared Function U() As BigInt 'Volume of the universe in planck-lengths Dim lRet As BigInt = New BigInt(10) ^ 35 'Planck-lengths per meter lRet = (lRet * 30000000) * 13700000 * (60 * 60 * 24 * 365) ' Diameter of Observable Universe in planck-lengths lRet = BigInt.TimesPi((lRet ^ 3) * 4) \ 3 ' Volume of the universe in Plank-lengths Return lRet End Function Public Shared Function TimesPi(pBigInt As BigInt) As BigInt Dim lOp As BigInt 'Just a handy rational approximation of Pi, in hex for performance Dim lSignificantDigits = (pBigInt.Log2 \ 4) + 3 'lOp = BigInt.FromBase10("1901870728566923076090143944714770339621590768313546337192526115562704339680963564320007808107929370299752345187688835741387003036853361285671158059867702399073227994426905220194699766118756059055619036488502928002591") 'Debug.Print("Multiple=" & BigInt.ToBase16(lOp)) lOp = BigInt.FromBase16(Left("5845B0A4C43FF041EE3CB64FE4AC283EC160121098D69A6E811E20511E3AE9B57DF4090D8855B3DC8BD649FA3756935283A0022779248D97ADD33C6B0BEAC74973DC124A3E1F0DBD6937F0E9E6975FF3C1C556B02A38ED94CE1F", lSignificantDigits)) Dim lRet As BigInt = pBigInt * lOp 'lOp = BigInt.FromBase10("605384255146420326102361023215940531716391478150345020739231253172134740688232476946000058713774549796561447468267746412874022717544100946587144148739626803435133473281606663121381125761746030151344353855924025288111") 'Debug.Print("Multiple=" & BigInt.ToBase16(lOp)) lOp = BigInt.FromBase16(Left("1C1911716363228A62BB598F0ACD9C1565D39E10D84CE34459AF8E7B7C871CF668B48356882A8239FC1FD6523E3B273E5232C420D9CB5564A5A2D1E571BD2D4ED25995EB9B7B06A9721C4929034443808B4F399D6714F9F1E5AF", lSignificantDigits)) 'Debug.Print("Dividend=" & BigInt.ToBase16(lOp)) lRet = lRet \ lOp Return lRet End Function Public Shared Function TestTimesPi(pReps As Integer) As Double Dim lOp As BigInt Dim lBigInt As BigInt = U() Dim lEnd As Double Dim lRet As BigInt Dim lStart As Double = Microsoft.VisualBasic.Timer For i As Integer = 1 To pReps lRet = TimesPi(lBigInt) Next i lEnd = Microsoft.VisualBasic.Timer Debug.Print(lEnd - lStart & " seconds for " & pReps & " pi calculations") Return lEnd - lStart End Function Private mBytes As List(Of Byte) Private mIsNegative As Boolean Public Function IsEven() As Boolean Return Not IsOdd() End Function Public Function IsOdd() As Boolean If IsZero() Then Return False Else Return mBytes(0) And 1 End Function Public Function Abs() As BigInt Dim lRet As New BigInt lRet.mBytes = New List(Of Byte) lRet.mBytes.AddRange(mBytes) lRet.Normalize() Return lRet End Function Public Sub Normalize() If mBytes Is Nothing Then mIsNegative = False Exit Sub End If If mBytes.Count > 0 Then While mBytes(mBytes.Count - 1) = 0 mBytes.RemoveAt(mBytes.Count - 1) End While End If If (mBytes.Count = 0) Then mIsNegative = False End If End Sub Public Sub New(pVal As Long) If pVal < 0 Then mIsNegative = True pVal = -pVal End If mBytes = New List(Of Byte) While pVal > 0 Dim lByte As Byte = pVal And 255 mBytes.Add(lByte) pVal = pVal >> 8 End While 'No need to normalize this End Sub Public Sub New(pBigInt As BigInt) mBytes = New List(Of Byte) mBytes.AddRange(pBigInt.mBytes.ToArray) mIsNegative = pBigInt.mIsNegative Normalize() End Sub Public Shared Operator -(ByVal class1 As BigInt) As BigInt Dim lRet As New BigInt(class1) lRet.mIsNegative = Not lRet.mIsNegative lRet.Normalize() Return lRet End Operator Public Shared Function Compare(ByVal class1 As BigInt, ByVal class2 As BigInt) As Integer class1.Normalize() class2.Normalize() If class1.IsZero Then If class2.IsZero Then Return 0 ElseIf class2.mIsNegative Then Return 1 Else Return -1 End If ElseIf class2.IsZero Then If class1.mIsNegative Then Return -1 Else Return 1 End If ElseIf class1.mIsNegative Then If class2.mIsNegative Then Return -Compare(-class1, -class2) Else Return -1 End If ElseIf class2.mIsNegative Then Return 1 End If 'Handle positive-positive comparison here Dim iLeft As Integer = class1.mBytes.Count - 1 Dim iRight As Integer = class2.mBytes.Count - 1 While iLeft > iRight If class1.mBytes(iLeft) <> 0 Then Return 1 End If iLeft -= 1 End While While iRight > iLeft If class2.mBytes(iRight) <> 0 Then Return -1 End If iRight -= 1 End While While iLeft >= 0 If class1.mBytes(iLeft) < class2.mBytes(iLeft) Then Return -1 ElseIf class1.mBytes(iLeft) > class2.mBytes(iLeft) Then Return 1 End If iLeft -= 1 End While Return 0 End Function Public Shared Operator <(ByVal class1 As BigInt, ByVal class2 As BigInt) As Boolean Select Case Compare(class1, class2) Case -1 Return True Case Else Return False End Select End Operator Public Shared Operator >(ByVal class1 As BigInt, ByVal class2 As BigInt) As Boolean Select Case Compare(class1, class2) Case 1 Return True Case Else Return False End Select End Operator Public Shared Operator <=(ByVal class1 As BigInt, ByVal class2 As BigInt) As Boolean Select Case Compare(class1, class2) Case 0, -1 Return True Case Else Return False End Select End Operator Public Shared Operator >=(ByVal class1 As BigInt, ByVal class2 As BigInt) As Boolean Select Case Compare(class1, class2) Case 0, 1 Return True Case Else Return False End Select End Operator Public Shared Operator =(ByVal class1 As BigInt, ByVal class2 As BigInt) As Boolean Select Case Compare(class1, class2) Case 0 Return True Case Else Return False End Select End Operator Public Shared Operator <>(ByVal class1 As BigInt, ByVal class2 As BigInt) As Boolean Select Case Compare(class1, class2) Case 0 Return False Case Else Return True End Select End Operator Public Function IsZero() As Boolean If mBytes Is Nothing Then Return True If mBytes.Count = 0 Then Return True For Each lByte In mBytes If lByte <> 0 Then Return False Next Return True End Function Public Shared Operator +(ByVal class1 As BigInt, ByVal class2 As Long) As BigInt Return class1 + New BigInt(class2) End Operator Public Shared Operator +(ByVal class1 As BigInt, ByVal class2 As BigInt) As BigInt If class1.mBytes Is Nothing Then Return class2 If class2.mBytes Is Nothing Then Return class1 Dim lBytes1 As Integer = class1.mBytes.Count Dim lBytes2 As Integer = class2.mBytes.Count Dim lBytes As New List(Of Byte) Dim lRemainder As Byte = 0 Dim i As Integer = 0 Dim lZeros As Integer = 0 While (i < lBytes1) Or (i < lBytes2) Or (lRemainder <> 0) Dim lByte1 As Integer = 0 Dim lByte2 As Integer = 0 Dim lTemp As Integer = 0 If i < lBytes1 Then lByte1 = class1.mBytes(i) If i < lBytes2 Then lByte2 = class2.mBytes(i) lTemp = lByte1 + lByte2 + lRemainder lRemainder = 0 If lTemp > 255 Then lRemainder = lTemp \ 256 lTemp -= 256 * lRemainder End If lBytes.Add(lTemp) If lTemp = 0 Then lZeros += 1 Else lZeros = 0 i += 1 End While While lZeros > 0 lBytes.RemoveAt(lBytes.Count - 1) lZeros -= 1 End While Dim lRet As New BigInt lRet.mBytes = lBytes Return lRet End Operator Public Shared Operator -(ByVal class1 As BigInt, ByVal class2 As Long) As BigInt Return class1 - New BigInt(class2) End Operator Public Shared Operator -(ByVal class1 As BigInt, ByVal class2 As BigInt) As BigInt Dim lResultIsNegative As Boolean Dim lLeft As BigInt Dim lRight As BigInt class1.Normalize() class2.Normalize() If class1.mIsNegative Then If class2.mIsNegative Then Return -(class1.Abs + class2.Abs) Else Return class1.Abs + class2 End If ElseIf class2.mIsNegative Then Return class1 + class2.Abs End If Select Case Compare(class1, class2) Case 0 Return New BigInt(0) Case -1 lResultIsNegative = True lLeft = class2 lRight = class1 Case 1 lResultIsNegative = False lLeft = class1 lRight = class2 Case Else Throw New InvalidOperationException("BigInt.vb encountered an invalid result when comparing numbers.") End Select 'Left is bigger than right, switch sign at the end if indicated Dim lBorrow As Integer = 0 Dim lRet As New BigInt(0) For i As Integer = 0 To lLeft.mBytes.Count - 1 Dim iLeft As Integer Dim iRight As Byte iLeft = lLeft.mBytes(i) - lBorrow If i >= lRight.mBytes.Count Then iRight = 0 Else iRight = lRight.mBytes(i) End If lBorrow = 0 While iLeft < iRight lBorrow += 1 iLeft += 256 End While lRet.mBytes.Add(iLeft - iRight) Next lRet.mIsNegative = lResultIsNegative lRet.Normalize() Return lRet End Operator Public Shared Function GrahamNotation(pBase As Integer, pArrows As Integer, pHeight As Integer) As BigInt Return GrahamNotation(New BigInt(pBase), pArrows, New BigInt(pHeight)) End Function Public Shared Function GrahamNotation(pBase As BigInt, pArrows As Integer, pHeight As BigInt) As BigInt If pArrows > 1 Then Return GrahamNotation(pBase, pArrows - 1, GrahamNotation(pBase, 1, pHeight)) End If Dim lRet As BigInt = pBase lRet = pBase ^ pHeight 'lRet = lRet ^ (pHeight - 1) Return lRet End Function Public Shared Operator *(ByVal class1 As BigInt, pByte As Byte) As BigInt Dim lBytes1 As Integer = class1.mBytes.Count Dim lOutBytes As New List(Of Byte) Dim lCarry As Long = 0 For i = 0 To lBytes1 - 1 Dim lTemp As Long = (CLng(class1.mBytes(i)) * pByte) + lCarry lCarry = 0 If lTemp > 255 Then lCarry = lTemp \ 256 lTemp = lTemp Mod 256 End If lOutBytes.Add(CByte(lTemp)) Next 'While lCarry > 255 If lCarry > 255 Then lOutBytes.Add(CByte(lCarry Mod 256)) lCarry = lCarry \ 256 End If 'End While If lCarry > 0 Then lOutBytes.Add(CByte(lCarry)) Dim lRet As New BigInt lRet.mBytes = lOutBytes lRet.mIsNegative = class1.mIsNegative Return lRet End Operator Public Shared Operator ^(ByVal class1 As BigInt, class2 As BigInt) As BigInt class2.Normalize() If class2.IsZero Then Return New BigInt(1) If class2 = New BigInt(1) Then Return class1 Dim lIsNegative As Boolean = False If class1.mIsNegative AndAlso (class2.mBytes(0) And 1) Then lIsNegative = True Dim lPow As New BigInt(class2) Dim lBase As New BigInt(class1) Dim l1 As New BigInt(1) Dim lSuperpow As New BigInt(l1) Dim lMultiplier As New BigInt(l1) Dim l2 As New BigInt(2) While lPow > l2 If lPow.IsOdd Then lPow -= l1 lMultiplier = lMultiplier * (lBase ^ lSuperpow) Else lPow = lPow >> 1 lSuperpow = lSuperpow << 1 End If End While lBase = lBase ^ lSuperpow If lPow = l2 Then lMultiplier = lMultiplier * lBase lBase = lBase * lMultiplier 'If lSuperpow > l1 Then lBase = lBase ^ lSuperpow Return lBase End Operator Public Shared Operator ^(ByVal class1 As BigInt, class2 As Integer) As BigInt Return class1 ^ New BigInt(class2) End Operator Public Shared Operator *(ByVal class1 As BigInt, class2 As Long) As BigInt Return class1 * New BigInt(class2) End Operator Public Shared Operator *(ByVal class1 As BigInt, class2 As BigInt) As BigInt Dim lTop As BigInt Dim lBottom As BigInt class1.Normalize() class2.Normalize() If class1.IsZero Or class2.IsZero Then Return New BigInt(0) Dim lResultIsNegative As Boolean = class1.mIsNegative Xor class2.mIsNegative If class1.mBytes.Count < class2.mBytes.Count Then lTop = class2 lBottom = class1 Else lTop = class1 lBottom = class2 End If Dim lRunningTotal As New BigInt For i = 0 To lBottom.mBytes.Count - 1 Dim lAdditive As BigInt = lTop * CByte(lBottom.mBytes(i)) For j = 1 To i lAdditive.mBytes.Insert(0, CByte(0)) Next lRunningTotal += lAdditive Next lRunningTotal.mIsNegative = lResultIsNegative lRunningTotal.Normalize() Return lRunningTotal End Operator Public Shared Function PowerOf2(pPower As Integer) As BigInt Dim lRet As BigInt = New BigInt(1) << (pPower - 1) Return lRet End Function Private Shared mPowersOf10 As Dictionary(Of Integer, BigInt) Public Shared Function ClearCachedPowers() If mPowersOf10 IsNot Nothing Then mPowersOf10.Clear() End If End Function Public Shared Function PowerOf10(pPower As Integer) As BigInt If pPower = 0 Then Return New BigInt(1) ElseIf pPower = 1 Then Return New BigInt(10) ElseIf mPowersOf10.ContainsKey(pPower) Then Return New BigInt(mPowersOf10(pPower)) Else mPowersOf10(pPower) = New BigInt(10) ^ pPower Return New BigInt(mPowersOf10(pPower)) End If End Function Public Shared Operator \(ByVal class1 As BigInt, class2 As BigInt) As BigInt Dim lResult As BigInt = New BigInt(0) Divide(class1, class2, lResult, New BigInt(0)) Return lResult End Operator Public Shared Operator /(ByVal class1 As BigInt, class2 As Long) As BigDecimal1 'Dim lResult As BigDecimal = New BigInt(0) 'Divide(class1, New BigInt(class2), lResult, New BigInt(0)) 'Return lResult End Operator Public Shared Operator /(ByVal class1 As BigInt, class2 As BigInt) As BigDecimal1 'Dim lResult As BigInt = New BigInt(0) 'Divide(class1, New BigInt(class2), lResult, New BigInt(0)) 'Return lResult End Operator Public Shared Operator \(ByVal class1 As BigInt, class2 As Long) As BigInt Dim lResult As BigInt = New BigInt(0) Divide(class1, New BigInt(class2), lResult, New BigInt(0)) Return lResult End Operator Public Shared Operator Mod(ByVal class1 As BigInt, class2 As BigInt) As BigInt Dim lResult As BigInt = New BigInt(0) Divide(class1, class2, New BigInt(0), lResult) Return lResult End Operator Public Shared Operator Mod(ByVal class1 As BigInt, class2 As Long) As BigInt Dim lResult As BigInt = New BigInt(0) Divide(class1, New BigInt(class2), New BigInt(0), lResult) Return lResult End Operator Public Function ToByte() As Byte Normalize() If IsZero() Then Return 0 Return mBytes(0) End Function Public Shared Sub SquareTest(pPower As Integer) Dim lRet As BigInt = (New BigInt(1) << pPower) - New BigInt(1) Debug.Print(lRet.ToString) End Sub Public Shared Sub SpeedTest2() Dim lBigNum As BigInt = New BigInt(10) Dim lTime1 As Double = Microsoft.VisualBasic.Timer lBigNum = lBigNum ^ 1000 Dim lTime2 As Double = Microsoft.VisualBasic.Timer Debug.Print((lTime2 - lTime1) & " seconds to calculate Googol^10") lTime1 = Microsoft.VisualBasic.Timer lBigNum = lBigNum ^ 50 lTime2 = Microsoft.VisualBasic.Timer Debug.Print((lTime2 - lTime1) & " seconds to raise that to the 50th power") Debug.Print("The result is " & lBigNum.Log2 & " bits long.") Debug.Print("Converting to decimal...") lTime1 = Microsoft.VisualBasic.Timer Debug.Print(lBigNum.ToString) lTime2 = Microsoft.VisualBasic.Timer Debug.Print("Converting to decimal took " & (lTime2 - lTime1) & " seconds.") End Sub Public Shared Sub SpeedTest3() Debug.Print("Generating 3 (arrow) 3") Dim lTime1 As Double = Microsoft.VisualBasic.Timer Dim lBigInt = BigInt.GrahamNotation(3, 1, 3) Dim lTime2 As Double = Microsoft.VisualBasic.Timer Debug.Print("Time elapsed: " & (lTime2 - lTime1)) Debug.Print(lBigInt.ToString) Debug.Print("Generating 3 (double-arrow) 3") lTime1 = Microsoft.VisualBasic.Timer lBigInt = BigInt.GrahamNotation(3, 2, 3) lTime2 = Microsoft.VisualBasic.Timer Debug.Print("Time elapsed: " & (lTime2 - lTime1)) Debug.Print(lBigInt.ToString) Exit Sub Debug.Print(lBigInt.mBytes.Count & " bytes") Debug.Print("Generating 3 (triple-arrow) 2") lTime1 = Microsoft.VisualBasic.Timer lBigInt = BigInt.GrahamNotation(3, 3, 2) lTime2 = Microsoft.VisualBasic.Timer Debug.Print("Time elapsed: " & (lTime2 - lTime1)) Debug.Print(lBigInt.ToString) Debug.Print(lBigInt.mBytes.Count & " bytes") Debug.Print("Generating 3 (triple-arrow) 3") lTime1 = Microsoft.VisualBasic.Timer lBigInt = BigInt.GrahamNotation(3, 3, 3) lTime2 = Microsoft.VisualBasic.Timer Debug.Print("Time elapsed: " & (lTime2 - lTime1)) Debug.Print(lBigInt.ToString) Debug.Print(lBigInt.mBytes.Count & " bytes") End Sub Public Shared Sub SpeedTest4() Dim lBigInt As BigInt = GrahamNotation(2, 4, 2) Debug.Print(lBigInt.ToString) End Sub Public Shared Sub SpeedTest() Dim lTime1 As Double = Microsoft.VisualBasic.Timer Dim j As Integer For i = 1 To 1000000 j = j + 1 Next Dim lTime2 As Double = Microsoft.VisualBasic.Timer Debug.Print("Integer: " & (lTime2 - lTime1)) Dim k As New BigInt(0) Dim l1 As New BigInt(1) For i = 1 To 10000 k = k + l1 Next lTime1 = Microsoft.VisualBasic.Timer Debug.Print("BigInt: " & (lTime1 - lTime2)) End Sub Public Function ToInt16() As Int16 Dim lRet As Int16 If IsZero() Then Return 0 If mBytes.Count > 1 Then lRet = lRet + (CLng(mBytes(1) And 127) << 8) If mBytes.Count > 0 Then lRet = lRet + mBytes(0) If mIsNegative Then Return -lRet Else Return lRet End Function Public Function ToInt32() As Int32 Dim lRet As Int32 If IsZero() Then Return 0 If mBytes.Count > 3 Then lRet = lRet + (CLng(mBytes(3) And 127) << 24) If mBytes.Count > 2 Then lRet = lRet + (CLng(mBytes(2)) << 16) If mBytes.Count > 1 Then lRet = lRet + (CLng(mBytes(1)) << 8) If mBytes.Count > 0 Then lRet = lRet + mBytes(0) If mIsNegative Then Return -lRet Else Return lRet End Function Private Shared Sub Divide(pDividend As BigInt, pDivisor As BigInt, ByRef pResult As BigInt, ByRef pModulus As BigInt) pDivisor.Normalize() If pDivisor.IsZero Then Throw New DivideByZeroException pDividend.Normalize() If pDividend.IsZero Then pResult = New BigInt(0) pModulus = New BigInt(0) Exit Sub End If Dim lResultIsNegative As Boolean = pDividend.mIsNegative Xor pDivisor.mIsNegative Dim lDividend As BigInt = pDividend.Abs Dim lDivisor As BigInt = pDivisor.Abs Select Case Compare(lDividend, lDivisor) Case -1 pResult = New BigInt(0) pModulus = New BigInt(lDividend) Exit Sub Case 0 pResult = New BigInt(1) pModulus = New BigInt(0) Exit Sub End Select ' Dividend is greater than divisor ' Multiply the dividend by 256 while Dim lShift As Integer Dim lRunningTotal As New BigInt(0) While Not lDividend.IsZero If lDividend < lDivisor Then pModulus = lDividend pResult = lRunningTotal Exit Sub End If lShift = Math.Truncate(lDividend.Log2_Dbl - lDivisor.Log2_Dbl) 'lShift = Math.Truncate(lDividend.Log2 - lDivisor.Log2) Dim lTestDivisor As BigInt = lDivisor << lShift If lTestDivisor > lDividend Then lTestDivisor = lTestDivisor >> 1 lShift -= 1 End If lRunningTotal += (New BigInt(1) << lShift) lDividend -= lTestDivisor End While pResult = lRunningTotal pModulus = New BigInt(0) Exit Sub End Sub Public Shared Operator <<(pBigInt As BigInt, pBits As Integer) As BigInt Dim lRet As New BigInt(pBigInt) Dim lBits As Integer = pBits pBigInt.Normalize() If lBits >= 8 Then Dim lInsertBytes((pBits \ 8) - 1) As Byte lRet.mBytes.InsertRange(0, lInsertBytes) lBits = lBits Mod 8 End If If lBits = 0 Then lRet.Normalize() Return lRet End If Dim lMostSignificantBit As Byte = Log2(lRet.mBytes(lRet.mBytes.Count - 1)) Dim lAvailableBits As Byte = 8 - lMostSignificantBit If lAvailableBits < lBits Then lRet.mBytes.Add(0) Dim lMaskLeft As Byte = (1 << (lBits + 1)) - 1 Dim lMaskRight As Byte = Not lMaskLeft For i = lRet.mBytes.Count - 1 To 1 Step -1 lRet.mBytes(i) = ((lRet.mBytes(i) << lBits) Or (lRet.mBytes(i - 1) >> (8 - lBits))) And 255 Next lRet.mBytes(0) = (lRet.mBytes(0) << lBits) And 255 Return lRet End Operator Public Shared Operator >>(pBigInt As BigInt, pBits As Integer) As BigInt Dim lRet As New BigInt(pBigInt) Dim lBits As Integer = pBits pBigInt.Normalize() If lBits >= 8 Then lRet.mBytes.RemoveRange(0, pBits = 8) lBits = lBits Mod 8 End If If lBits = 0 Then lRet.Normalize() Return lRet End If Dim lMostSignificantBit As Byte = Log2(lRet.mBytes(lRet.mBytes.Count - 1)) Dim lAvailableBits As Byte = 8 - lMostSignificantBit If lAvailableBits < lBits Then lRet.mBytes.Add(0) Dim lMaskLeft As Byte = (1 << (lBits + 1)) - 1 Dim lMaskRight As Byte = Not lMaskLeft For i = 0 To lRet.mBytes.Count - 2 lRet.mBytes(i) = ((lRet.mBytes(i) >> lBits) Or (lRet.mBytes(i + 1) << (8 - lBits))) And 255 Next lRet.mBytes(lRet.mBytes.Count - 1) = (lRet.mBytes(lRet.mBytes.Count - 1) >> lBits) And 255 Return lRet End Operator Public Function Log2() As Long Normalize() If IsZero() Then Return 0 Return ((mBytes.Count - 1) * 8) + Log2(mBytes(mBytes.Count - 1)) End Function Public Function Log2_Dbl() As Double Normalize() If IsZero() Then Return 0 Dim lBits As Integer = (mBytes.Count - 1) * 8 Dim lDivisor As Double = 1 Dim lRunningTotal As Double = lBits + Log2_Dbl(mBytes(mBytes.Count - 1)) For i = mBytes.Count - 2 To Math.Max(mBytes.Count - 8, 0) Step -1 lDivisor = lDivisor * 256 lRunningTotal += (CDbl(Log2_Dbl(mBytes(i))) / lDivisor) Next Return lRunningTotal End Function Public Overrides Function ToString() As String Return BigInt.ToBase10(Me) End Function Public Shared Function ToBaseX(pBigInt As BigInt, pBase As Byte) As String If pBase < 2 Then Throw New ArgumentException("Cannot display as base less than 2") If pBase > 2 Then Throw New ArgumentException("Cannot display as base greater than 16") pBigInt.Normalize() If pBigInt.IsZero Then Return "0" Dim aChars() As Char = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"} Dim lRet As New System.Text.StringBuilder() If pBigInt.mIsNegative Then lRet.Append("-") lRet.Append("&(" & pBase & ")") Dim lByte As Byte = (pBigInt Mod pBase).ToByte If lByte And &HF0 Then lRet.Append(aChars(lByte)) End If If lByte And &HF Then lRet.Append(aChars(lByte And &HF)) End If For i = pBigInt.mBytes.Count - 2 To 0 Step -1 lByte = pBigInt.mBytes(i) lRet.Append(aChars(lByte >> 4) & aChars(lByte And 15)) Next Return lRet.ToString End Function Public Shared Function ToBase16(pBigInt As BigInt) As String pBigInt.Normalize() If pBigInt.IsZero Then Return "0" Dim aChars() As Char = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"} Dim lRet As New System.Text.StringBuilder() If pBigInt.mIsNegative Then lRet.Append("-") lRet.Append("&H") Dim lByte As Byte = pBigInt.mBytes(pBigInt.mBytes.Count - 1) If lByte And &HF0 Then lRet.Append(aChars(lByte >> 4)) End If If lByte And &HF Then lRet.Append(aChars(lByte And &HF)) End If For i = pBigInt.mBytes.Count - 2 To 0 Step -1 lByte = pBigInt.mBytes(i) lRet.Append(aChars(lByte >> 4) & aChars(lByte And 15)) Next Return lRet.ToString End Function Public Function ToBase16() As String Return BigInt.ToBase16(Me) End Function Public Shared Function FromBase10(pSource As String) As BigInt Dim lMode As Byte = 1 Dim lIsNegative As Boolean Dim lNB As New System.Text.StringBuilder Dim lDec As Integer = -1 Dim lShiftDirection As Char Dim lShiftAmt As String For Each lChar In pSource Select Case lMode Case 1 Select Case lChar Case " ", "+" Case "-" lIsNegative = True lMode = 2 Case "0" 'ignore leading zeros Case "1" To "9" lNB.Append(lChar) lMode = 2 Case "." lDec = lNB.Length lMode = 3 Case Else Throw New InvalidCastException End Select Case 2 Select Case lChar Case "," Case "0" To "9" lNB.Append(lChar) Case "." lDec = lNB.Length lMode = 3 Case "E" lMode = 4 Case Else Throw New InvalidCastException End Select Case 3 Select Case lChar Case "," Case "0" To "9" lNB.Append(lChar) Case "E" lMode = 4 lShiftDirection = "+" Case Else Throw New InvalidCastException End Select Case 4 Select Case lChar Case "+", "-" lShiftDirection = lChar lMode = 5 Case "0" Case "1" To "9" lShiftAmt = lShiftAmt & lChar lMode = 6 Case Else Throw New InvalidCastException End Select Case 5 Select Case lChar Case "0" Case "1" To "9" lShiftAmt = lShiftAmt & lChar lMode = 6 Case Else Throw New InvalidCastException End Select Case 6 Select Case lChar Case "0" To "9" lShiftAmt = lShiftAmt & lChar lMode = 6 Case Else Throw New InvalidCastException End Select End Select Next If lDec = -1 Then lDec = lNB.Length + 1 Dim lAsDecimal As String If lShiftAmt = "" Then lAsDecimal = lNB.ToString ElseIf lShiftDirection = "+" Then lDec = lDec + Val(lShiftAmt) If lDec > (lNB.Length + 1) Then lAsDecimal = lNB.ToString & New String("0", (lDec - lNB.Length) - 1) Else lAsDecimal = lNB.ToString.Substring(0, lDec - 1) End If ElseIf lShiftDirection = "-" Then lDec = lDec - Val(lShiftAmt) If lDec < 1 Then Return New BigInt(0) Else lAsDecimal = lNB.ToString.Substring(0, lDec - 1) End If End If 'lAsDecimal is now a clean, unsigned decimal with scientific notation expanded Dim l10 As BigInt = New BigInt(10) Dim lTens As BigInt = New BigInt(1) Dim lRet As BigInt = New BigInt(0) For i = lAsDecimal.Length - 1 To 0 Step -1 Dim lAdditive As BigInt = lTens * New BigInt(Asc(lAsDecimal.Substring(i, 1)) - 48) lRet += lAdditive lTens = lTens * l10 Next lRet.mIsNegative = lIsNegative lRet.Normalize() Return lRet End Function Public Shared Function FromBase16(pSource As String) As BigInt Dim lProc As New Stack(Of Byte) Dim lTemp As String = "" Dim lRet As New BigInt(0) For i = 0 To pSource.Length - 1 Dim lChar As Char = pSource.Substring(i, 1) Dim lAsc As Integer = Asc(lChar) Select Case lAsc Case 48 To 57 lTemp = lTemp & lChar Case 65 To 70 lTemp = lTemp & lChar End Select If Len(lTemp) = 2 Then Dim lByte As Byte = 0 lAsc = Asc(lTemp.Substring(0, 1)) Select Case lAsc Case 48 To 57 lByte = (lAsc - 48) << 4 Case 65 To 70 lByte = (lAsc - 55) << 4 End Select lAsc = Asc(lTemp.Substring(1, 1)) Select Case lAsc Case 48 To 57 lByte = lByte + (lAsc - 48) Case 65 To 70 lByte = lByte + (lAsc - 55) End Select lTemp = "" lRet.mBytes.Insert(0, lByte) End If Next If lTemp <> "" Then Select Case Asc(lTemp) Case 48 To 57 lRet = lRet << 4 lRet += New BigInt(Asc(lTemp) - 48) Case 65 To 70 lRet = lRet << 4 lRet += New BigInt(Asc(lTemp) - 55) End Select End If lRet.Normalize() Return lRet End Function Public Shared Function ToBase10(pBigInt As BigInt) As String Dim lRemaining As BigInt = pBigInt Dim lStack As New Stack(Of Char) Dim lMod As BigInt = Nothing Dim lDigit As Byte Dim l10 As New BigInt(10) Dim l10K As New BigInt(10000) Dim l1B As New BigInt(1000000000) Dim l1Googol As BigInt = New BigInt(0) If pBigInt.Log2 >= 332 Then l1Googol = New BigInt(10000) ^ 25 Dim l1GoogolE10 As BigInt = New BigInt(0) If pBigInt.Log2 >= 3321 Then l1GoogolE10 = l1Googol ^ 10 pBigInt.Normalize() If pBigInt.IsZero Then Return "0" Dim lLastUpdate As Double = Microsoft.VisualBasic.Timer Dim lStartTime As DateTime = Now Dim lStartDigits As Integer = lRemaining.Log2 Dim lStackSize As Long = 0 Do If (Not l1GoogolE10.IsZero) AndAlso (lRemaining > l1GoogolE10) Then Divide(lRemaining, l1GoogolE10, lRemaining, lMod) Dim lText As String = lMod.ToString.PadLeft(1000, "0") For i = lText.Length - 1 To 0 Step -1 lStack.Push(lText.Substring(i, 1)) Next lStackSize += lText.Length ElseIf (Not l1Googol.IsZero) AndAlso (lRemaining > l1Googol) Then Divide(lRemaining, l1Googol, lRemaining, lMod) Dim lText As String = lMod.ToString.PadLeft(100, "0") For i = lText.Length - 1 To 0 Step -1 lStack.Push(lText.Substring(i, 1)) Next lStackSize += lText.Length ElseIf lRemaining > l1B Then Divide(lRemaining, l1B, lRemaining, lMod) Dim lText As String = Format(lMod.ToInt32, "000000000") For i = lText.Length - 1 To 0 Step -1 lStack.Push(lText.Substring(i, 1)) Next lStackSize += lText.Length ElseIf lRemaining > l10K Then Divide(lRemaining, l10K, lRemaining, lMod) Dim lText As String = Format(lMod.ToInt16, "0000") For i = lText.Length - 1 To 0 Step -1 lStack.Push(lText.Substring(i, 1)) Next lStackSize += lText.Length Else Divide(lRemaining, l10, lRemaining, lMod) lStack.Push(CStr(lMod.ToByte)) lStackSize += 1 End If If (Microsoft.VisualBasic.Timer - lLastUpdate) > 10 Then Dim lLog2 As Integer = lRemaining.Log2 If lLog2 < lStartDigits Then Debug.Print(lLog2 & " significant digits remaining.") Dim lTimeSpent As TimeSpan = Now.Subtract(lStartTime) Dim lUnitTime As Double = lTimeSpent.TotalSeconds / (lStartDigits - lLog2) Dim lCompletion As DateTime = Now.AddSeconds(lUnitTime * lLog2 * (lLog2 / lStartDigits) / 3) Debug.Print("Estimated Completion: " & Format(lCompletion, "M/d/yyyy HH:mm:ss")) Dim lDigitRatio As Double = lStackSize / (lStartDigits - lLog2) Debug.Print("Estimated Output Digits: " & (lStackSize + CInt(lDigitRatio * lLog2))) lLastUpdate = Microsoft.VisualBasic.Timer End If End If Loop Until lRemaining.IsZero If pBigInt.mIsNegative Then lStack.Push("-") Dim lRet As New System.Text.StringBuilder While lStack.Count lRet.Append(lStack.Pop) End While If Now - lStartTime > New TimeSpan(0, 1, 0) Then Using lwriter As New IO.StreamWriter("c:\temp\Calculation.txt", False) lwriter.WriteLine(lRet.ToString) lwriter.Close() lwriter.Dispose() End Using End If Return lRet.ToString End Function Public Shared Function Log2(pByte As Byte) As Byte Dim lRet As Byte While pByte <> 0 lRet += 1 pByte = pByte >> 1 End While Return lRet End Function Public Shared Function Log2(pInteger As Integer) As Byte Dim lRet As Byte If pInteger < 0 Then Throw New InvalidOperationException("BigInt cannot take the logarithm of a negative number.") While pInteger <> 0 lRet += 1 pInteger = pInteger >> 1 End While Return lRet End Function Public Shared Function Log2_Dbl(pByte As Byte) As Double Dim lRet As Double = 8 If pByte = 0 Then Return 0 While (pByte And &H80) = 0 lRet -= 1 pByte = pByte << 1 End While pByte = pByte << 1 Dim lDivisor As Integer = 2 While pByte <> 0 If pByte And &H80 Then lRet = lRet + 1 / lDivisor End If lDivisor *= 2 pByte = pByte << 1 End While Return lRet End Function Public Shared Function Log2_Dbl(pInteger As Integer) As Double Dim lRet As Double = 8 If pInteger = 0 Then Return 0 While (pInteger And &H8000) = 0 lRet -= 1 pInteger = pInteger << 1 End While pInteger = pInteger << 1 Dim lDivisor As Integer = 2 While pInteger <> 0 If pInteger And &H8000 Then lRet = lRet + 1 / lDivisor End If lDivisor *= 2 pInteger = pInteger << 1 End While Return lRet End FunctionEnd Structure 这篇关于.NET中的BigDecimal超过28位的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 1403页,肝出来的.. 09-07 00:49