document.write('
Data hosted with ♥ by Pastebin.com - Download Raw - See Original
  1. \'http://tizzyt-archive.blogspot.com/2015/03/quick-and-dirty-net-bigdecimal.html
  2. Imports System.Numerics
  3. Public Structure BigDecimal
  4.     Private ILen, MLen As Integer
  5.     Private value As BigInteger
  6.  
  7.     Public Shared ReadOnly Zero As New BigDecimal(0)
  8.     Public Shared ReadOnly ZeroPointOne As New BigDecimal(0.1)
  9.     Public Shared ReadOnly ZeroPointFive As New BigDecimal(0.5)
  10.     Public Shared ReadOnly One As New BigDecimal(1)
  11.     Public Shared ReadOnly Two As New BigDecimal(2)
  12.     Public Shared ReadOnly ThreePointTwo As New BigDecimal(3.2)
  13.     Public Shared ReadOnly Four As New BigDecimal(4)
  14.     Public Shared ReadOnly Five As New BigDecimal(5)
  15.     Public Shared ReadOnly TwentyFive As New BigDecimal(25)
  16.     Public Shared ReadOnly TwoHundredThirtyNine As New BigDecimal(239)
  17.     Public Shared ReadOnly FiftySevenThousandOneHundredTwentyOne As New BigDecimal(57121)
  18.  
  19. #Region "Properties"
  20.     \'Property for number of digits in BigDecimal\'s integral part
  21.     Public ReadOnly Property IntegralLength() As Integer
  22.         Get
  23.             Return ILen
  24.         End Get
  25.     End Property
  26.  
  27.     \'Property for number of digits in BigDecimal\'s mantissa part
  28.     Public ReadOnly Property MantissaLength() As Integer
  29.         Get
  30.             Return ILen
  31.         End Get
  32.     End Property
  33.  
  34.     \'Property whether BigDecimal is one
  35.     Public ReadOnly Property IsOne() As Boolean
  36.         Get
  37.             If ILen = 1 AndAlso MLen = 0 Then Return value.IsOne Else Return False
  38.         End Get
  39.     End Property
  40.  
  41.     \'Property whether BigDecimal is zero
  42.     Public ReadOnly Property IsZero() As Boolean
  43.         Get
  44.             Return value.IsZero
  45.         End Get
  46.     End Property
  47.  
  48.     \'Property of the BigDecimal\'s sign (negative, zero, positive)
  49.     Public ReadOnly Property Sign() As Integer
  50.         Get
  51.             Return value.Sign
  52.         End Get
  53.     End Property
  54.  
  55.     \'Property of whether BigDecimal is a power of two
  56.     Public ReadOnly Property IsPowerOfTwo() As Boolean
  57.         Get
  58.             If MLen = 0 AndAlso value.IsPowerOfTwo _
  59.                 Then Return True _
  60.                 Else Return False
  61.         End Get
  62.     End Property
  63.  
  64.     \'Property of whether BigDecimal is Even
  65.     Public ReadOnly Property IsEven As Boolean
  66.         Get
  67.             If MLen = 0 AndAlso value.IsEven _
  68.                 Then Return True _
  69.                 Else Return False
  70.         End Get
  71.     End Property
  72. #End Region
  73.  
  74. #Region "Unsigned Integer Constructors"
  75.     \'Construct a BigDecimal number from Byte
  76.     Sub New(ByVal Num As Byte)
  77.         value = New BigInteger(Num)
  78.         ILen = Num.ToString.Length
  79.         MLen = 0
  80.     End Sub
  81.  
  82.     \'Construct a BigDecimal number from UShort
  83.     Sub New(ByVal Num As UShort)
  84.         value = New BigInteger(Num)
  85.         ILen = Num.ToString.Length
  86.         MLen = 0
  87.     End Sub
  88.  
  89.     \'Construct a BigDecimal number from UInteger
  90.     Sub New(ByVal Num As UInteger)
  91.         value = New BigInteger(Num)
  92.         ILen = Num.ToString.Length
  93.         MLen = 0
  94.     End Sub
  95.  
  96.     \'Construct a BigDecimal number from ULong
  97.     Sub New(ByVal Num As ULong)
  98.         value = New BigInteger(Num)
  99.         ILen = Num.ToString.Length
  100.         MLen = 0
  101.     End Sub
  102. #End Region
  103.  
  104. #Region "Signed Integral Constructors"
  105.     \'Construct a BigDecimal number from Signed Byte
  106.     Sub New(ByVal Num As SByte)
  107.         Dim t As String = Num.ToString & "."
  108.         value = New BigInteger(Num)
  109.         If t.StartsWith("-") Then
  110.             t = (t.Remove(0, 1) & ".").Trim("0"c)
  111.             ILen = t.Length - 1
  112.         Else
  113.             ILen = t.Length - 1
  114.         End If
  115.         MLen = 0
  116.     End Sub
  117.  
  118.     \'Construct a BigDecimal number from Short
  119.     Sub New(ByVal Num As Short)
  120.         Dim t As String = Num.ToString & "."
  121.         value = New BigInteger(Num)
  122.         If t.StartsWith("-") Then
  123.             t = (t.Remove(0, 1) & ".").Trim("0"c)
  124.             ILen = t.Length - 1
  125.         Else
  126.             ILen = t.Length - 1
  127.         End If
  128.         MLen = 0
  129.     End Sub
  130.  
  131.     \'Construct a BigDecimal number from Integer
  132.     Sub New(ByVal Num As Integer)
  133.         Dim t As String = Num.ToString & "."
  134.         value = New BigInteger(Num)
  135.         If t.StartsWith("-") Then
  136.             t = (t.Remove(0, 1) & ".").Trim("0"c)
  137.             ILen = t.Length - 1
  138.         Else
  139.             ILen = t.Length - 1
  140.         End If
  141.         MLen = 0
  142.     End Sub
  143.  
  144.     \'Construct a BigDecimal number from Long
  145.     Sub New(ByVal Num As Long)
  146.         Dim t As String = Num.ToString & "."
  147.         value = New BigInteger(Num)
  148.         If t.StartsWith("-") Then
  149.             t = (t.Remove(0, 1) & ".").Trim("0"c)
  150.             ILen = t.Length - 1
  151.         Else
  152.             ILen = t.Length - 1
  153.         End If
  154.         MLen = 0
  155.     End Sub
  156.  
  157.     \'Construct a BigDecimal number from BigInteger
  158.     Sub New(ByVal Num As BigInteger)
  159.         Dim t As String = Num.ToString & "."
  160.         value = Num
  161.         If t.StartsWith("-") Then
  162.             t = (t.Remove(0, 1) & ".").Trim("0"c)
  163.             ILen = t.Length - 1
  164.         Else
  165.             ILen = t.Length - 1
  166.         End If
  167.         MLen = 0
  168.     End Sub
  169. #End Region
  170.  
  171. #Region "Decimal Constructors"
  172.     \'Construct a BigDecimal number from Decimal
  173.     Sub New(ByVal Num As Decimal)
  174.         Parse(CStr(Num))
  175.     End Sub
  176.  
  177.     \'Construct a BigDecimal number from Single
  178.     Sub New(ByVal Num As Single)
  179.         Parse(CStr(Num))
  180.     End Sub
  181.  
  182.     \'Construct a BigDecimal number from Double
  183.     Sub New(ByVal Num As Double)
  184.         Parse(CStr(Num))
  185.     End Sub
  186.  
  187.     \'Construct a BigDecimal number from Byte array
  188.     Sub New(ByVal Num() As Byte)
  189.         ILen = BitConverter.ToInt32({Num(0), Num(1), Num(2), Num(3)}, 0)
  190.         MLen = BitConverter.ToInt32({Num(4), Num(5), Num(6), Num(7)}, 0)
  191.         Dim VBytes(Num.Length - 9) As Byte
  192.         Array.Copy(Num, 8, VBytes, 0, VBytes.Length)
  193.         value = New BigInteger(VBytes)
  194.     End Sub
  195.  
  196.     \'Construct a BigDecimal number from String
  197.     Sub New(ByVal Num As String)
  198.         Parse(Num)
  199.     End Sub
  200. #End Region
  201.  
  202. #Region "Main Parser"
  203.     \'Parses and sets the attributes for BigDecimal
  204.     Private Sub Parse(ByVal Num As String)
  205.         Dim neg As Boolean = False
  206.         Dim dec As Boolean = True
  207.         Dim Str As String = ""
  208.         For Each digit As Char In Num
  209.             Select Case digit
  210.                 Case "-"c : neg = True
  211.                 Case "0"c To "9"c : Str &= digit
  212.                 Case "."c : If dec Then Str &= "." : dec = False
  213.             End Select
  214.         Next
  215.         If Str.Contains(".") Then
  216.             Str = Str.Trim("0"c)
  217.             ILen = Str.IndexOf(".")
  218.             MLen = Str.Length - ILen - 1
  219.             If Str.EndsWith(".") Then Str = Str.Substring(0, Str.Length - 1)
  220.         Else
  221.             Str = (Str & ".").Trim("0"c)
  222.             Str = Str.Substring(0, Str.Length - 1)
  223.             ILen = Str.Length
  224.             MLen = 0
  225.         End If
  226.         If Str = "." OrElse Str = "" Then
  227.             Num = "0"
  228.         Else
  229.             If Str.StartsWith(".") Then Num = "0" & Str Else Num = Str
  230.             If neg Then Num = "-" & Str
  231.         End If
  232.         value = BigInteger.Parse(Num.Replace(".", String.Empty))
  233.     End Sub
  234. #End Region
  235.  
  236. #Region "General Functions"
  237.     \'Does a comparison between the current BigInteger and another returning the first difference
  238.     Public Function CompareTo(ByRef other As BigDecimal) As Integer
  239.         If other.value.Sign = value.Sign Then \'Compares decimal sign
  240.             If other.ILen = ILen Then \'Compares the integral size
  241.                 If other.MLen = MLen Then \'Compares the mantissa size
  242.                     If other.value = value Then \'Compares the actual value
  243.                         Return 0 \'the two are the same
  244.                     Else
  245.                         If other.value > value Then
  246.                             Return -6 \'Other decimal value is greater
  247.                         Else
  248.                             Return 6 \'Other decimal value is smaller
  249.                         End If
  250.                     End If
  251.                 Else
  252.                     If other.MLen > MLen Then
  253.                         Return -5 \'Other decimal has a larger mantissa length
  254.                     Else
  255.                         Return 5 \'Other decimal has a smaller mantissa length
  256.                     End If
  257.                 End If
  258.             Else
  259.                 If other.ILen > ILen Then
  260.                     Return -4 \'Other decimal has a larger integral length
  261.                 Else
  262.                     Return 4 \'Other decimal has a smaller integral length
  263.                 End If
  264.             End If
  265.         Else
  266.             Select Case value.Sign
  267.                 Case 0 \'This decimal is zero
  268.                     Select Case other.value.Sign
  269.                         Case -1 \'Other decimal is negative
  270.                             Return 3
  271.                         Case 1 \'Other decimal is positive
  272.                             Return -1
  273.                     End Select
  274.                 Case -1 \'This decimal is negative
  275.                     Select Case other.value.Sign
  276.                         Case 0 \'Other decimal is zero
  277.                             Return -3
  278.                         Case 1 \'Other decimal is positive
  279.                             Return -2
  280.                     End Select
  281.                 Case 1 \'This decimal is positive
  282.                     Select Case other.value.Sign
  283.                         Case -1 \'Other decimal is negative
  284.                             Return 2
  285.                         Case 0 \'Other decimal is zero
  286.                             Return 1
  287.                     End Select
  288.             End Select
  289.         End If
  290.         Return 7 \'Shouldn\'t get this far, defaults to not same, Unknown error
  291.     End Function
  292.  
  293.     \'Represents BigDecimal number as string
  294.     Public Overrides Function ToString() As String
  295.         If value.Sign = 0 Then Return "0"
  296.         Dim AsString As String = value.ToString
  297.         If value.Sign = -1 Then
  298.             AsString = AsString.Remove(0, 1).PadLeft(MLen, "0"c).Insert(ILen, ".")
  299.             If ILen = 0 Then Return "-0" & AsString Else Return "-" & AsString.Trim("."c)
  300.         End If
  301.         AsString = AsString.PadLeft(MLen, "0"c).Insert(ILen, ".")
  302.         If ILen = 0 Then Return "0" & AsString Else Return AsString.Trim("."c)
  303.     End Function
  304.  
  305.     \'Represents BigDecimal as string with a specified character for thousands delimiter
  306.     Private Const ValDig As String = "-.0123456789" \'Valid characters for bigdecimal string
  307.     Public Overloads Function ToString(ByVal Spacer As Char) As String
  308.         If ValDig.Contains(Spacer) Then Throw New Exception("Invalid Character for use as spacer")
  309.         Dim str As String = ToString()
  310.         If Not Spacer = "" Then
  311.             If value.Sign = -1 Then
  312.                 If MLen = 0 Then
  313.                     For i = str.Length - 3 To 2 Step -3 : str = str.Insert(i, Spacer) : Next
  314.                 Else
  315.                     For i = str.IndexOf(".") - 3 To 2 Step -3 : str = str.Insert(i, Spacer) : Next
  316.                 End If
  317.             Else
  318.                 If MLen = 0 Then
  319.                     For i = str.Length - 3 To 1 Step -3 : str = str.Insert(i, Spacer) : Next
  320.                 Else
  321.                     For i = str.IndexOf(".") - 3 To 1 Step -3 : str = str.Insert(i, Spacer) : Next
  322.                 End If
  323.             End If
  324.         End If
  325.         Return str
  326.     End Function
  327.  
  328.     \'Returns the current BigDecimal represented as an array of bytes
  329.     Public Function ToByteArray() As Byte()
  330.         Dim RBytes As New List(Of Byte)
  331.         RBytes.AddRange(BitConverter.GetBytes(ILen))
  332.         RBytes.AddRange(BitConverter.GetBytes(MLen))
  333.         RBytes.AddRange(value.ToByteArray)
  334.         Return RBytes.ToArray
  335.     End Function
  336. #End Region
  337.  
  338. #Region "Basic Operators"
  339.     \'Does addition on two BigDecimal numbers
  340.     Public Shared Operator +(ByVal Num1 As BigDecimal, ByVal Num2 As BigDecimal) As BigDecimal
  341.         Dim L As Integer = Num1.MLen
  342.         Dim D As Integer = 0
  343.         If Num1.MLen > Num2.MLen Then
  344.             D = Num1.MLen - Num2.MLen
  345.             Num2.value = Pow10(Num2, D)
  346.         Else
  347.             L = Num2.MLen
  348.             D = Num2.MLen - Num1.MLen
  349.             Num1.value = Pow10(Num1, D)
  350.         End If
  351.         Return PowN10(BigInteger.Add(Num1.value, Num2.value).ToString, L)
  352.     End Operator
  353.  
  354.     \'Does subtraction on two BigDecimal numbers
  355.     Public Shared Operator -(ByVal Num1 As BigDecimal, ByVal Num2 As BigDecimal) As BigDecimal
  356.         Dim L As Integer = Num1.MLen
  357.         Dim D As Integer = 0
  358.         If Num1.MLen > Num2.MLen Then
  359.             D = Num1.MLen - Num2.MLen
  360.             Num2.value = Pow10(Num2, D)
  361.         Else
  362.             L = Num2.MLen
  363.             D = Num2.MLen - Num1.MLen
  364.             Num1.value = Pow10(Num1, D)
  365.         End If
  366.         Return PowN10(BigInteger.Subtract(Num1.value, Num2.value).ToString, L)
  367.     End Operator
  368.  
  369.     \'Does multiplication on two BigDecimal numbers
  370.     Public Shared Operator *(ByVal Num1 As BigDecimal, ByVal Num2 As BigDecimal) As BigDecimal
  371.         Dim D As Integer = 0
  372.         If Num1.MLen >= Num2.MLen _
  373.             Then D = Num1.MLen - Num2.MLen _
  374.             Else D = Num2.MLen - Num1.MLen
  375.         Dim O As Integer = Num1.MLen + Num2.MLen + D * 2
  376.         Num1.value = Pow10(Num1, D)
  377.         Num2.value = Pow10(Num2, D)
  378.         Return PowN10(BigInteger.Multiply(Num1.value, Num2.value).ToString, O)
  379.     End Operator
  380.  
  381.     \'Does division on two BigDecimal numbers
  382.     Public Shared Operator /(ByVal Num1 As BigDecimal, ByVal Num2 As BigDecimal) As BigDecimal
  383.         Return Div(Num1, Num2)
  384.     End Operator
  385.  
  386.     \'Does division on two BigDecimal numbers with specified precision (no rounding)
  387.     Public Shared Function Div(ByVal Num1 As BigDecimal, ByVal Num2 As BigDecimal,
  388.                                   Optional ByVal Precision As Integer = -1) As BigDecimal
  389.         If Num2.value.IsZero Then Throw New DivideByZeroException
  390.         Dim P As Integer = (Num1.MLen * Num2.MLen) + Num1.ILen + Num2.ILen + 1
  391.         Dim D As Integer = Math.Abs(Num1.MLen - Num2.MLen)
  392.         If Precision > -1 Then P = Precision
  393.         If Num1.MLen >= Num2.MLen Then
  394.             Num1.value = Pow10(Num1, P)
  395.             Num2.value = Pow10(Num2, D)
  396.         Else
  397.             Num1.value = Pow10(Num1, D + P)
  398.         End If
  399.         Return PowN10(BigInteger.Divide(Num1.value, Num2.value).ToString, P)
  400.     End Function
  401.  
  402.     \'Raise BigDecimal to the power of an integer
  403.     Public Shared Operator ^(ByVal Num1 As BigDecimal, ByVal Num2 As Integer) As BigDecimal
  404.         Return Pow(Num1, Num2)
  405.     End Operator
  406.  
  407.     \'Raise BigDecimal to power of integer with specified precision for negatives(no rounding)
  408.     Public Shared Function Pow(ByVal Num1 As BigDecimal, ByVal Num2 As Integer,
  409.                                Optional ByVal Precision As Integer = -1) As BigDecimal
  410.         If Num2 = 0 Then Return One
  411.         If Num2 < 0 Then
  412.             Num2 = Math.Abs(Num2)
  413.             Dim L As Integer = Num1.MLen * Num2
  414.             Dim R As BigDecimal = PowN10(BigInteger.Pow(Num1.value, Num2).ToString, L)
  415.             If Precision = -1 Then Precision = R.ILen + R.MLen
  416.             Return Div(One, R, Precision)
  417.         Else
  418.             Dim L As Integer = Num1.MLen * Num2
  419.             Dim R As BigInteger = BigInteger.Pow(Num1.value, Num2)
  420.             Return PowN10(R.ToString, L)
  421.         End If
  422.     End Function
  423.  
  424.     \'Does Modular arithmetic on two BigDecimal numbers
  425.     Public Shared Operator Mod(ByVal Num1 As BigDecimal, ByVal Num2 As BigDecimal) As BigDecimal
  426.         If Num2.ILen > Num1.ILen Then Return Num1
  427.         If Num2.value.IsZero Then Throw New DivideByZeroException
  428.         Dim L As Integer = Num1.MLen
  429.         Dim D As Integer = Math.Abs(Num1.MLen - Num2.MLen)
  430.         If Num1.MLen >= Num2.MLen Then
  431.             Num2.value = Pow10(Num2, D)
  432.         Else
  433.             L = Num2.MLen
  434.             Num1.value = Pow10(Num1, D)
  435.         End If
  436.         Return PowN10(New BigDecimal(BigInteger.ModPow(Num1.value, 1, Num2.value)), L)
  437.         \'Return PowN10(BigInteger.ModPow(Num1.value, 1, Num2.value).ToString, L)
  438.     End Operator
  439.  
  440.     \'Does equal comparison on two BigDecimal numbers
  441.     Public Shared Operator =(ByVal Num1 As BigDecimal, ByVal Num2 As BigDecimal) As Boolean
  442.         If Num1.value.Sign = Num2.value.Sign _
  443.             AndAlso Num1.ILen = Num2.ILen _
  444.             AndAlso Num1.MLen = Num2.MLen _
  445.             AndAlso Num1.value = Num2.value _
  446.             Then Return True _
  447.             Else Return False
  448.     End Operator
  449.  
  450.     \'Does greater than less than comparison on two BigDecimal numbers
  451.     Public Shared Operator <>(ByVal Num1 As BigDecimal, ByVal Num2 As BigDecimal) As Boolean
  452.         If Num1.value.Sign = Num2.value.Sign _
  453.             AndAlso Num1.ILen = Num2.ILen _
  454.             AndAlso Num1.MLen = Num2.MLen _
  455.             AndAlso Num1.value = Num2.value _
  456.             Then Return False _
  457.             Else Return True
  458.     End Operator
  459.  
  460.     \'Does greater than comparison on two BigDecimal numbers
  461.     Public Shared Operator >(ByVal Num1 As BigDecimal, ByVal Num2 As BigDecimal) As Boolean
  462.         If Num1.Sign > Num2.Sign OrElse Num1.ILen > Num1.ILen Then Return True
  463.         Dim L As Integer = Num1.MLen
  464.         Dim D As Integer = 0
  465.         If Num1.MLen > Num2.MLen Then
  466.             D = Num1.MLen - Num2.MLen
  467.             Num2.value = Pow10(Num2, D)
  468.         Else
  469.             L = Num2.MLen
  470.             D = Num2.MLen - Num1.MLen
  471.             Num1.value = Pow10(Num1, D)
  472.         End If
  473.         If BigInteger.Subtract(Num1.value, Num2.value) > 0 Then Return True
  474.         Return False
  475.     End Operator
  476.  
  477.     \'Does less than comparison on two BigDecimal numbers
  478.     Public Shared Operator <(ByVal Num1 As BigDecimal, ByVal Num2 As BigDecimal) As Boolean
  479.         If Num1.Sign > Num2.Sign OrElse Num1.ILen > Num1.ILen Then Return True
  480.         If Num1.MLen = Num2.MLen Then
  481.             Return Num1.value < Num2.value
  482.         Else
  483.             Dim L As Integer = Num1.MLen
  484.             Dim D As Integer = 0
  485.             If Num1.MLen > Num2.MLen Then
  486.                 D = Num1.MLen - Num2.MLen
  487.                 Num2.value = Pow10(Num2, D)
  488.             Else
  489.                 L = Num2.MLen
  490.                 D = Num2.MLen - Num1.MLen
  491.                 Num1.value = Pow10(Num1, D)
  492.             End If
  493.             If BigInteger.Subtract(Num1.value, Num2.value) < 0 Then Return True
  494.         End If
  495.         Return False
  496.     End Operator
  497.  
  498.     \'Does greater than or equal to comparison on two BigDecimal numbers
  499.     Public Shared Operator >=(ByVal Num1 As BigDecimal, ByVal Num2 As BigDecimal) As Boolean
  500.         If Num1.Sign > Num2.Sign OrElse Num1.ILen > Num1.ILen Then Return True
  501.         If Num1.MLen = Num2.MLen Then
  502.             Return Num1.value >= Num2.value
  503.         Else
  504.             Dim L As Integer = Num1.MLen
  505.             Dim D As Integer = 0
  506.             If Num1.MLen > Num2.MLen Then
  507.                 D = Num1.MLen - Num2.MLen
  508.                 Num2.value = Pow10(Num2, D)
  509.             Else
  510.                 L = Num2.MLen
  511.                 D = Num2.MLen - Num1.MLen
  512.                 Num1.value = Pow10(Num1, D)
  513.             End If
  514.             If BigInteger.Subtract(Num1.value, Num2.value) >= 0 Then Return True
  515.         End If
  516.         Return False
  517.     End Operator
  518.  
  519.     \'Does less than or equal to comparison on two BigDecimal numbers
  520.     Public Shared Operator <=(ByVal Num1 As BigDecimal, ByVal Num2 As BigDecimal) As Boolean
  521.         If Num1.Sign > Num2.Sign OrElse Num1.ILen > Num1.ILen Then Return True
  522.         If Num1.MLen = Num2.MLen Then
  523.             Return Num1.value <= Num2.value
  524.         Else
  525.             Dim L As Integer = Num1.MLen
  526.             Dim D As Integer = 0
  527.             If Num1.MLen > Num2.MLen Then
  528.                 D = Num1.MLen - Num2.MLen
  529.                 Num2.value = Pow10(Num2, D)
  530.             Else
  531.                 L = Num2.MLen
  532.                 D = Num2.MLen - Num1.MLen
  533.                 Num1.value = Pow10(Num1, D)
  534.             End If
  535.             If BigInteger.Subtract(Num1.value, Num2.value) <= 0 Then Return True
  536.         End If
  537.         Return False
  538.     End Operator
  539. #End Region
  540.  
  541. #Region "Misc"
  542.     \'Multiplies a BigDecimal number by 10 raised to a specified exponent
  543.     Private Shared Function Pow10(ByVal value As BigDecimal, ByVal exponent As Integer) As BigInteger
  544.         If value.value = 0 OrElse exponent = 0 Then Return value.value
  545.         Return BigInteger.Multiply(value.value, BigInteger.Pow(10, exponent))
  546.     End Function
  547.  
  548.     \'Moves around the decimal value to mimic a BigDecimal multiplied by 10 to a negative power
  549.     Private Shared Function PowN10(ByVal value As String, ByVal exponent As Integer) As BigDecimal
  550.         If value.StartsWith("-") Then
  551.             value = value.Remove(0, 1).PadLeft(exponent, "0"c)
  552.             Return New BigDecimal("-" & value.Insert(value.Length - exponent, "."))
  553.         End If
  554.         value = value.PadLeft(exponent, "0"c)
  555.         Return New BigDecimal(value.Insert(value.Length - exponent, "."))
  556.     End Function
  557.  
  558.     \'Raises a bigdecimal to a negative integer power
  559.     Private Shared Function PowN10(ByVal Num As BigDecimal, ByVal exponent As Integer) As BigDecimal
  560.         If exponent = 0 Then Return One
  561.         Dim EXP As BigDecimal = ZeroPointOne
  562.         For i = 1 To Math.Abs(exponent) : EXP *= ZeroPointOne : Next
  563.         Return Num * EXP
  564.     End Function
  565.  
  566.     \'Finds the square root of a bigdecimal number given the precision, no decimals if not specified
  567.     Public Shared Function Sqrt(ByVal Num As BigDecimal,
  568.                             Optional ByVal Precision As Integer = 0) As BigDecimal
  569.         Dim ourGuess As BigDecimal = Div(Num, Two, Precision)
  570.         While True
  571.             Dim result As BigDecimal = Div(Num, ourGuess, Precision)
  572.             Dim average As BigDecimal = Div((ourGuess + result), Two, Precision)
  573.             If average = ourGuess Then Return average Else ourGuess = average
  574.         End While
  575.         Return Zero
  576.     End Function
  577.  
  578.     \'Returns PI to the specified decimal place
  579.     Public Shared Function Pi(ByVal Precision As Integer) As BigDecimal
  580.         Precision += 4 \'Increase precision internally to account for rounding
  581.         Dim answer As BigDecimal = Zero
  582.         Dim term5 As BigDecimal = ThreePointTwo
  583.         Dim term239 As BigDecimal = Div(Four, TwoHundredThirtyNine, Precision)
  584.         Dim term5m As BigDecimal
  585.         Dim term239m As BigDecimal
  586.         Dim n5 As Integer = 0
  587.         Dim n239 As Integer = 0
  588.         While True
  589.             term5m = Div(term5, New BigDecimal(n5 * 2 + 1), Precision)
  590.             If n5 Mod 2 = 0 Then answer += term5m Else answer -= term5m
  591.             term5 = Div(term5, TwentyFive, Precision)
  592.             n5 += 1
  593.             If term5m.IsZero Then Exit While
  594.         End While
  595.         While True
  596.             term239m = Div(term239, New BigDecimal(n239 * 2 + 1), Precision)
  597.             If n239 Mod 2 = 0 Then answer -= term239m Else answer += term239m
  598.             term239 = Div(term239, FiftySevenThousandOneHundredTwentyOne, Precision)
  599.             n239 += 1
  600.             If term239m.IsZero Then Exit While
  601.         End While
  602.         Return Div(answer, One, Precision - 4)
  603.     End Function
  604.  
  605.     \'Returns Phi to the specified decimal place
  606.     Public Shared Function Phi(ByVal Precision As Integer) As BigDecimal
  607.         Return (One + Sqrt(Five, Precision)) * ZeroPointFive
  608.     End Function
  609.  
  610.     \'Returns Tau to the specified decimal place
  611.     Public Shared Function Tau(ByVal Precision As Integer) As BigDecimal
  612.         Return Div(Pi(Precision + 1) * Two, One, Precision)
  613.     End Function
  614.  
  615.     \'Returns Pythagoras\' constant to the specified decimal place
  616.     Public Shared Function PythagorasConst(ByVal Precision As Integer) As BigDecimal
  617.         Return Sqrt(Two, Precision)
  618.     End Function
  619. #End Region
  620. End Structure
');