Code archives/Algorithms/BlitzMax Big Numbers
This code has been declared by its author to be Public Domain code.
Download source code
| |||||
The code below represents a set of functions for BlitzMax that can be used to add and subtract big integers without loss of precision. Values are stored in decimal format as strings.(x ="42" ) The code below has both the functions and a simple program demonstrating the addition and subtraction functions. The subtraction function is simplified by using the nine's complement (see Wikipedia: Method of complements) of the minuend. Basically, it's a math trick that allows the function the calculate subtraction by doing addition. It avoids the need to "borrow" when subtracting. Currently, this version can only handle positive integers. One possible use of these functions is to keep track of a player's very large score without loss of precision. This code has not been rigorously tested. So, if you find any bugs, please post them in the comments below. Thanks, Spencer | |||||
'------------------------------------------------- 'Example Program Global x:String = "0" Global y:String = "0" Global R:String = "0" x = "9999999999999999999999999999999999999" y = "1" R = BigNumbers.Add(x,y) Print R x = "11900" y = "11800" R = BigNumbers.Subtract(x,y) Print R End '------------------------------------------------- '*************************************************************************************************************** 'BigNumbers '*************************************************************************************************************** Type BigNumbers Const EnumCompareResultLessThan = -1 Const EnumCompareResultEqualTo = 0 Const EnumCompareResultGreaterThan = 1 Function GetNinesComplement:String(Value:String,MinuendDigitCount:Int) Local Result:String For Local CharPos:Int = 0 To Value.Length-1 Step 1 Result = Result + Trim(String( 9-Int(Chr(Value[CharPos]))) ) Next While Result.Length < MinuendDigitCount Result = "9" + Result Wend Return Result EndFunction Function StringPadLeft:String(SourceValue:String,Value:String,Count:Int) For Local x:Int = 1 To Count Step 1 SourceValue = Value + SourceValue Next Return SourceValue EndFunction Function StripLeadingZeros:String(Value:String) For Local CharPos:Int = 0 To Value.Length-1 Step 1 If( Chr(Value[CharPos]) <> " " ) And ( Chr(Value[CharPos]) <> "0" ) Then Return Trim(Value[CharPos..]) EndIf Next Return "0" 'value was all spaces and/or zeros EndFunction Function CompareNumbers:Int(Number1:String,Number2:String) Local Difference:Int = Number2.Length - Number1.Length Local Number1Padded:String = BigNumbers.StringPadLeft(Number1,"0",(Difference>0)*Difference) Local Number2Padded:String = BigNumbers.StringPadLeft(Number2,"0",(Difference<0)*(Abs(Difference))) Local Digit1:Byte Local Digit2:Byte For Local CharPos:Int = 0 To Number1Padded.Length-1 Step 1 Digit1 = Int(Chr(Number1Padded[CharPos])) Digit2 = Int(Chr(Number2Padded[CharPos])) If(Digit1 > Digit2)Then Return BigNumbers.EnumCompareResultGreaterThan ElseIf(Digit2 > Digit1)Then Return BigNumbers.EnumCompareResultLessThan EndIf Next Return BigNumbers.EnumCompareResultEqualTo EndFunction Function GetLargest:String(Number1:String,Number2:String) If(BigNumbers.CompareNumbers(Number2,Number1) = BigNumbers.EnumCompareResultGreaterThan)Then Return Number2 Else Return Number1 EndIf EndFunction Function GetSmallest:String(Number1:String,Number2:String) If(BigNumbers.CompareNumbers(Number2,Number1) = BigNumbers.EnumCompareResultLessThan)Then Return Number2 Else Return Number1 EndIf EndFunction Function Add:String(Number1:String,Number2:String) Local Difference:Int = Number2.Length - Number1.Length Local Number1Padded:String = BigNumbers.StringPadLeft(Number1,"0",(Difference>0)*Difference) Local Number2Padded:String = BigNumbers.StringPadLeft(Number2,"0",(Difference<0)*(Abs(Difference))) Local Result:String Local A:Byte Local B:Byte Local C:Byte Local R:Byte For Local CharPos:Int = Number1Padded.Length-1 To 0 Step -1 C = (R > 9) A = Int(Chr(Number1Padded[CharPos])) B = Int(Chr(Number2Padded[CharPos])) R = A + B + C Result = Right(String(R),1) + Result Next If(C > 0) Then Result = "1" + Result EndIf Return BigNumbers.StripLeadingZeros(Result) EndFunction Function Subtract:String(Number1:String,Number2:String) Local Smallest:String = BigNumbers.GetSmallest(Number1,Number2) Local Largest:String = BigNumbers.GetLargest(Number1,Number2) Local NinesComp:String = BigNumbers.GetNinesComplement(Smallest,Largest.Length) Local TempResult:String = BigNumbers.Add(Largest,NinesComp) 'nines complement of smaller number TempResult = BigNumbers.Add(TempResult,"1") TempResult = BigNumbers.StripLeadingZeros(TempResult) TempResult = TempResult[1..] Return BigNumbers.StripLeadingZeros(TempResult) EndFunction EndType '*************************************************************************************************************** 'End of BigNumbers '*************************************************************************************************************** |
Comments
None.
Code Archives Forum