Jump to content

Re-written Fibonacci Calculator


BoonPek
 Share

Recommended Posts

Hello,

I have never used AutoIt for the past six months an now I'm starting to get sucky at coding. I just finished my new build so I moved back to programming with AutoIt. I didn't have any ideas on what to start with so I browsed through the other scripts and found one Fibonacci script and decided to make a calculator.

It uses BigNum.au3 to process large numbers. The file is unoptimized as I rushed through it, I'll fix that later on. The only thing I want to add on now is the time it takes to calculate in the format HH:MM:SS:MS, is there a function in AutoIt to convert milliseconds into that format?

Program:

#include "BigNum.au3"
#include <GuiConstants.au3>
#include <EditConstants.au3>
#include <WindowsConstants.au3>

Local $A, $B, $C, $iCount = 2
Global $Hours, $Minutes, $Seconds, $Milliseconds

GUICreate("Fibonacci Calculator", 400, 360, -1, -1)
$Enter = GUICtrlCreateLabel("Sequence Number:", 10, 10, 100, 20)
$Input = GUICtrlCreateInput("5000", 110, 10, 200, 20)
$Start = GUICtrlCreateButton("Start", 320, 10, 70, 20)
$Data = GUICtrlCreateEdit("", 10, 40, 380, 200, BitOR($ES_AUTOVSCROLL, $WS_VSCROLL, $ES_MULTILINE, $ES_READONLY))
$Success = GUICtrlCreateLabel("", 10, 10, 380, 15)
GUICtrlSetState($Success, $GUI_HIDE)
$Progress = GUICtrlCreateProgress(10, 250, 380, 25)
$Time = GUICtrlCreateLabel("", 10, 285, 380, 20)
GUISetState(@SW_SHOW)
While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            ExitLoop
        Case $Start
            Calculate()
    EndSwitch
WEnd


Func Calculate()
    Disable()
    $Number = GUICtrlRead($Input)
    $A = 0
    $B = 1
    $C = $A + $B
    $Times = TimerInit()
    Do
        $iCount += 1
        $A = $B
        $B = $C
        $C = _BigNum_Add($A, $B)
        ProgressUpdate()
    Until $iCount = $Number
    $End = TimerDiff($Times)
    Finish()
EndFunc   ;==>Calculate

Func ProgressUpdate()
    $Number = GUICtrlRead($Input)
    GUICtrlSetData($Progress, $iCount / $Number * 100)
EndFunc   ;==>ProgressUpdate

Func Disable()
    GUICtrlSetState($Enter, $GUI_DISABLE)
    GUICtrlSetState($Input, $GUI_DISABLE)
    GUICtrlSetState($Start, $GUI_DISABLE)
EndFunc   ;==>Disable


Func Finish()
    GUICtrlDelete($Enter)
    GUICtrlDelete($Input)
    GUICtrlDelete($Start)
    GUICtrlSetState($Success, $GUI_SHOW)
    GUICtrlSetData($Success, "You have successfully calculated the " & $iCount & "th term in the Fibonacci Sequence!")
    GUICtrlSetData($Data, $C)
    GuiCtrlSetData($Time, "It took " & $End & " milliseconds to calculate the " & $iCount & "th term in the Fibonacci Sequence")
EndFunc   ;==>Finish

BigNum.au3

#include-once

Global Const $BigNum_Debug=False

; #INDEX# =======================================================================================================================
; Title .........: BigNum
; AutoIt Version : 3.2.12.1
; Language ......: English
; Description ...: Perform calculations with big numbers
; ===============================================================================================================================

; #CURRENT# =====================================================================================================================
;_BigNum_Add
;_BigNum_Sub
;_BigNum_Mul
;_BigNum_Div
;_BigNum_Mod
;_BigNum_Round
;_BigNum_Compare
;_BigNum_Swap
; ===============================================================================================================================

; #INTERNAL_USE_ONLY#============================================================================================================
;_BigNum_CheckNegative
;_BigNum_DivAdd
;_BigNum_DivComp
;_BigNum_DivSub
;_BigNum_Div_DivisorGreater14
;_BigNum_Div_DivisorMaxLen14
;_BigNum_InsertDecimalSeparator
;_BigNum_StringIsDecimal
;_BigNum_IsValid
; ===============================================================================================================================




; #FUNCTION# ;====================================================================================
;
; Name...........: _BigNum_Add
; Description ...: Addition $sX + $sY
; Syntax.........: _BigNum_Add($sX, $sY)
; Parameters ....: $sX - StringNumber: Minus"-" Digits"0"..."9" Separator"." ("-1234567890.12345")
;                  $sY - StringNumber: Minus"-" Digits"0"..."9" Separator"." ("-1234567890.12345")
; Return values .: Success - Result $sX + $sY
;                  Failure - 0, sets @error to 1 if $sX/$sY not valid StringNumber
; Author ........: Eukalyptus www.autoit.de
;
; ;===============================================================================================
Func _BigNum_Add($sX, $sY)
    If _BigNum_IsValid($sX, $sY) Then Return SetError(1, 0, 0)
    Local $iNeg = _BigNum_CheckNegative($sX, $sY), $sNeg = ""
    If $iNeg = 3 Then $sNeg = "-"
    If $iNeg = 1 Then Return _BigNum_Sub($sY, $sX)
    If $iNeg = 2 Then Return _BigNum_Sub($sX, $sY)
    If $BigNum_Debug Then Local $BN_File=FileOpen(@ScriptDir & "\BigNum_Debug.txt",2)
    Local $iDec = _BigNum_StringIsDecimal($sX, $sY)
    Local $iTmp = StringLen($sX), $iLen = StringLen($sY), $iCar = 0, $sRet = ""
    If $BigNum_Debug Then FileWrite($BN_File," " & _BigNum_DS($iLen-$iTmp,"0") & $sX & " + " & @CRLF & " " & _BigNum_DS($iTmp-$iLen,"0") & $sY & @CRLF)
    If $iLen < $iTmp Then $iLen = $iTmp
    If $BigNum_Debug Then FileWrite($BN_File," " & _BigNum_DS($iLen,"-") & @CRLF)
    For $i = 1 To $iLen Step 18
        $iTmp = Int(StringRight($sX, 18)) + Int(StringRight($sY, 18)) + $iCar
        $sX = StringTrimRight($sX, 18)
        $sY = StringTrimRight($sY, 18)
        If ($iTmp > 999999999999999999) Then
            $iTmp = StringRight($iTmp, 18)
            $sRet = $iTmp & $sRet
            If $BigNum_Debug Then FileWrite($BN_File,_BigNum_DS($iLen-$i-StringLen($iTmp)+2) & $iTmp & _BigNum_DS($i) & "+" & $iCar & @CRLF)
            $iCar = 1
        Else
            If $BigNum_Debug Then FileWrite($BN_File,_BigNum_DS($iLen-$i-StringLen($iTmp)+2) & $iTmp & _BigNum_DS($i) & "+" & $iCar & @CRLF)
            $iTmp = StringRight("000000000000000000" & $iTmp, 18)
            $sRet = $iTmp & $sRet
            $iCar = 0
        EndIf
    Next
    $sRet = StringRegExpReplace($iCar & $sRet, "^0+([^0]|0$)", "\1", 1)
    If $iDec > 0 Then $sRet = _BigNum_InsertDecimalSeparator($sRet, $iDec, $iDec)
    If $sRet = "0" Then $sNeg = ""
    If $BigNum_Debug Then 
        FileWrite($BN_File," " & _BigNum_DS($iLen,"-") & @CRLF)
        FileWrite($BN_File,_BigNum_DS($iLen - StringLen($sRet)+1) & $sRet)
        FileClose($BN_File)
    EndIf
    Return $sNeg & $sRet
EndFunc   ;==>_BigNum_Add



; #FUNCTION# ;====================================================================================
;
; Name...........: _BigNum_Sub
; Description ...: Subtraction $sX - $sY
; Syntax.........: _BigNum_Sub($sX, $sY)
; Parameters ....: $sX - StringNumber: Minus"-" Digits"0"..."9" Separator"." ("-1234567890.12345")
;                  $sY - StringNumber: Minus"-" Digits"0"..."9" Separator"." ("-1234567890.12345")
; Return values .: Success - Result $sX - $sY
;                  Failure - 0, sets @error to 1 if $sX/$sY not valid StringNumber
; Author ........: Eukalyptus www.autoit.de
;
; ;===============================================================================================
Func _BigNum_Sub($sX, $sY)
    If _BigNum_IsValid($sX, $sY) Then Return SetError(1, 0, 0)
    Local $iNeg = _BigNum_CheckNegative($sX, $sY), $bNeg = False
    If $iNeg = 3 Then Return _BigNum_Add("-" & $sX, $sY)
    If $iNeg = 1 Then Return "-" & _BigNum_Add($sX, $sY)
    If $iNeg = 2 Then Return _BigNum_Add($sX, $sY)
    If $BigNum_Debug Then Local $BN_File=FileOpen(@ScriptDir & "\BigNum_Debug.txt",2)
    Local $iDec = _BigNum_StringIsDecimal($sX, $sY)
    If _BigNum_Compare($sX, $sY) = -1 Then $bNeg = _BigNum_Swap($sX, $sY)
    Local $iTmp = StringLen($sX), $iLen = StringLen($sY), $iCar = 0, $sRet = ""
    If $BigNum_Debug Then FileWrite($BN_File," " & _BigNum_DS($iLen-$iTmp,"0") & $sX & " - " & @CRLF & " " & _BigNum_DS($iTmp-$iLen,"0") & $sY & @CRLF)
    If $iLen < $iTmp Then $iLen = $iTmp
    If $BigNum_Debug Then FileWrite($BN_File," " & _BigNum_DS($iLen,"-") & @CRLF)
    For $i = 1 To $iLen Step 18
        $iTmp = Int(StringRight($sX, 18)) - Int(StringRight($sY, 18)) - $iCar
        $sX = StringTrimRight($sX, 18)
        $sY = StringTrimRight($sY, 18)
        If $iTmp < 0 Then
            $iTmp = 1000000000000000000 + $iTmp
            If $BigNum_Debug Then FileWrite($BN_File,_BigNum_DS($iLen-$i-StringLen($iTmp)+2) & $iTmp & _BigNum_DS($i) & "-" & $iCar & @CRLF)
            $iCar = 1
        Else
            If $BigNum_Debug Then FileWrite($BN_File,_BigNum_DS($iLen-$i-StringLen($iTmp)+2) & $iTmp & _BigNum_DS($i) & "-" & $iCar & @CRLF)
            $iCar = 0
        EndIf
        $sRet = StringRight("0000000000000000000" & $iTmp, 18) & $sRet
    Next
    $sRet = StringRegExpReplace($iCar & $sRet, "^0+([^0]|0$)", "\1", 1)
    If $iDec > 0 Then $sRet = _BigNum_InsertDecimalSeparator($sRet, $iDec, $iDec)
    If $BigNum_Debug Then 
        FileWrite($BN_File," " & _BigNum_DS($iLen,"-") & @CRLF)
        FileWrite($BN_File,_BigNum_DS($iLen - StringLen($sRet)+1) & $sRet)
        FileClose($BN_File)
    EndIf
    If $bNeg = True And $sRet <> "0" Then
        Return "-" & $sRet
    Else
        Return $sRet
    EndIf
EndFunc   ;==>_BigNum_Sub



; #FUNCTION# ;====================================================================================
;
; Name...........: _BigNum_Mul
; Description ...: Multiplication $sX * $sY
; Syntax.........: _BigNum_Mul($sX, $sY)
; Parameters ....: $sX - StringNumber: Minus"-" Digits"0"..."9" Separator"." ("-1234567890.12345")
;                  $sY - StringNumber: Minus"-" Digits"0"..."9" Separator"." ("-1234567890.12345")
; Return values .: Success - Result $sX * $sY
;                  Failure - 0, sets @error to 1 if $sX/$sY not valid StringNumber
; Author ........: Eukalyptus www.autoit.de
;
; ;===============================================================================================
Func _BigNum_Mul($sX, $sY)
    If _BigNum_IsValid($sX, $sY) Then Return SetError(1, 0, 0)
    Local $iNeg = _BigNum_CheckNegative($sX, $sY), $sNeg = ""
    Local $iDec = _BigNum_StringIsDecimal($sX, $sY)
    If $BigNum_Debug Then 
        Local $BN_File=FileOpen(@ScriptDir & "\BigNum_Debug.txt",2), $BN_X=StringLen($sX)
        FileWrite($BN_File," " & $sX & " * " & $sY & " = " & @CRLF)
        FileWrite($BN_File," " & _BigNum_DS($BN_X+StringLen($sY)+3,"-") & @CRLF)
    EndIf
    Local $aX = StringRegExp($sX, '\A.{' & 6 - (Ceiling(StringLen($sX) / 6) * 6 - StringLen($sX)) & '}|.{6}+', 3)
    Local $aY = StringRegExp($sY, '\A.{' & 6 - (Ceiling(StringLen($sY) / 6) * 6 - StringLen($sY)) & '}|.{6}+', 3)
    Local $aRet[UBound($aX) + UBound($aY) - 1]
    For $j = 0 To UBound($aX) - 1
        For $i = 0 To UBound($aY) - 1
            If $BigNum_Debug Then 
                FileWrite($BN_File," " & _BigNum_DS(StringLen($aX[0])+$j*6-StringLen($aX[$j])) & $aX[$j] & _BigNum_DS($BN_X-(StringLen($aX[0])+$j*6)) & " * " & _BigNum_DS(StringLen($aY[0])+$i*6-StringLen($aY[$i])) & $aY[$i])
                FileWrite($BN_File,"   " & _BigNum_DS(((UBound($aY)-1-$i)*6)+($i*15+$j*15)) & $aX[$j] * $aY[$i] & @CRLF)
            EndIf
            $aRet[$j + $i] += $aX[$j] * $aY[$i]
        Next
    Next
    If $BigNum_Debug Then
        FileWrite($BN_File," " & _BigNum_DS($BN_X+StringLen($sY)+3) & _BigNum_DS($i*15+$j*15,"-") & @CRLF)
        FileWrite($BN_File," " & _BigNum_DS($BN_X+StringLen($sY)+6))
        For $i=0 to UBound($aRet)-1
            FileWrite($BN_File, $aRet[$i] & _BigNum_DS(15-StringLen($aRet[$i])))
        Next
        FileWrite($BN_File,@CRLF & @CRLF)
        For $i=0 to UBound($aRet)-1
            FileWrite($BN_File,_BigNum_DS($BN_X+StringLen($sY)) & _BigNum_DS($i*6+15-StringLen($aRet[$i])) & $aRet[$i] & @CRLF)
        Next
        FileWrite($BN_File,_BigNum_DS($BN_X+StringLen($sY)) & _BigNum_DS(15-StringLen($aRet[0])) & _BigNum_DS($i*6,"-") & @CRLF)
    EndIf
    Local $sRet = "", $iCar = 0, $iTmp
    For $i = UBound($aRet) - 1 To 0 Step -1
        $aRet[$i] += $iCar
        $iCar = Floor($aRet[$i] / 1000000)
        $iTmp = Mod($aRet[$i], 1000000)
        If $iTmp <= 1000000 Then $iTmp = StringRight("000000" & $iTmp, 6)
        $sRet = $iTmp & $sRet
    Next
    If $iCar > 0 Then $sRet = $iCar & $sRet
    $sRet = StringRegExpReplace($sRet, "^0+([^0]|0$)", "\1", 1)
    If ($iNeg = 1 Or $iNeg = 2) And $sRet <> "0" Then $sNeg = "-"
    If $iDec > 0 Then $sRet = _BigNum_InsertDecimalSeparator($sRet, $iDec * 2, $iDec * 2)
    If $BigNum_Debug Then 
        FileWrite($BN_File,_BigNum_DS($BN_X+StringLen($sY)) & _BigNum_DS(15-StringLen($aRet[0])) & $sRet)
        FileClose($BN_File)
    EndIf
    Return $sNeg & $sRet
EndFunc   ;==>_BigNum_Mul



; #FUNCTION# ;====================================================================================
;
; Name...........: _BigNum_Div
; Description ...: Division $sX / $sY
; Syntax.........: _BigNum_Div($sX, $sY, [$iD = 0])
; Parameters ....: $sX - StringNumber: Minus"-" Digits"0"..."9" Separator"." ("-1234567890.12345")
;                  $sY - StringNumber: Minus"-" Digits"0"..."9" Separator"." ("-1234567890.12345")
;                  $iD [optional] - Number of Decimalplaces
; Return values .: Success - Result $sX / $sY
;                  Failure - 0, sets @error to 1 if $sX/$sY not valid StringNumber
; Author ........: Eukalyptus www.autoit.de
;
; ;===============================================================================================
Func _BigNum_Div($sX, $sY, $iD = 0)
    If _BigNum_IsValid($sX, $sY) Then Return SetError(1, 0, 0)
    Local $iNeg = _BigNum_CheckNegative($sX, $sY), $sNeg = ""
    Local $iDec = _BigNum_StringIsDecimal($sX, $sY), $sMod
    If $sX = 0 Or $sY = 0 Then Return "0"
    If $sY = "1" Then Return $sNeg & $sX
    While StringLeft($sX,1)="0"
        $sX=StringTrimLeft($sX,1)
        $iDec+=1
    WEnd
    While StringLeft($sY,1)="0"
        $sY=StringTrimLeft($sY,1)
        $iDec+=1
    WEnd
    Local $sRet = "", $iLnX = StringLen($sX), $iLnY = StringLen($sY), $iTmp, $iCnt, $sTmp, $iDe1 = 0
    If $iD > 0 Then $iDe1 += $iD
    If $iNeg = 1 Or $iNeg = 2 Then $sNeg = "-"
    $iTmp = _BigNum_Compare($sX, $sY)
    If $iTmp = -1 Then
        For $iCnt = $iLnX To $iLnY
            $sX &= 0
            $iDe1 += 1
        Next
    EndIf
    If $iTmp = 0 Then Return $sNeg & "1"
    If $iD = -1 Then $iD = $iDec * 2
    For $iCnt = 1 To $iD
        $sX &= "0"
    Next
    If $iLnY > 14 Then
        $sRet = _BigNum_Div_DivisorGreater14($sX, $sY, $sMod)
    Else
        $sRet = _BigNum_Div_DivisorMaxLen14($sX, $sY, $sMod)
    EndIf
    If $iDe1 > 0 Then $sRet = _BigNum_InsertDecimalSeparator($sRet, $iDe1, $iD)
    If $sRet = "0" Then
        Return "0"
    Else
        Return $sNeg & $sRet
    EndIf
EndFunc   ;==>_BigNum_Div



; #FUNCTION# ;====================================================================================
;
; Name...........: _BigNum_Mod
; Description ...: Modulo Mod($sX, $sY)
; Syntax.........: _BigNum_Mod($sX, $sY)
; Parameters ....: $sX - StringNumber: Minus"-" Digits"0"..."9" Separator"." ("-1234567890.12345")
;                  $sY - StringNumber: Minus"-" Digits"0"..."9" Separator"." ("-1234567890.12345")
; Return values .: Success - Result Mod($sX, $sY)
;                  Failure - 0, sets @error to 1 if $sX/$sY not valid StringNumber
; Author ........: Eukalyptus www.autoit.de
;
; ;===============================================================================================
Func _BigNum_Mod($sX, $sY)
    If _BigNum_IsValid($sX, $sY) Then Return SetError(1, 0, 0)
    If $sY = 0 Or $sY = 1 Then Return "0"
    Local $sRes = $sX
    Local $iNeg = _BigNum_CheckNegative($sX, $sY)
    Local $iDec = _BigNum_StringIsDecimal($sX, $sY)
    If _BigNum_Compare($sX, $sY) < 0 Then Return $sRes
    Local $sRet = "", $iLnX = StringLen($sX), $iLnY = StringLen($sY)
    If $iLnY > 14 Then
        _BigNum_Div_DivisorGreater14($sX, $sY, $sRet)
    Else
        _BigNum_Div_DivisorMaxLen14($sX, $sY, $sRet)
    EndIf
    $sRet = _BigNum_InsertDecimalSeparator($sRet, $iDec, StringLen($sRet))
    If ($iNeg = 3 Or $iNeg = 1) And $sRet <> "0" Then $sRet = "-" & $sRet
    Return $sRet
EndFunc   ;==>_BigNum_Mod



; #FUNCTION# ;====================================================================================
;
; Name...........: _BigNum_Round
; Description ...: Round $sX to $iD Decimalplaces
; Syntax.........: _BigNum_Round($sX, $iD)
; Parameters ....: $sX - StringNumber: Minus"-" Digits"0"..."9" Separator"." ("-1234567890.12345")
;                  $iD - Number of Decimalplaces
; Return values .: Success - Result Round($sX, $iD)
;                  Failure - 0, sets @error to 1 if $sX not valid StringNumber
; Author ........: Eukalyptus www.autoit.de
;
; ;===============================================================================================
Func _BigNum_Round($sX, $iD)
    If _BigNum_IsValid($sX, $sX) Then Return SetError(1, 0, 0)
    Local $sTmp = 0, $sRet, $sRes = $sX
    Local $iNeg = _BigNum_CheckNegative($sX, $sTmp)
    Local $iDec = _BigNum_StringIsDecimal($sX, $sTmp)
    If $iD > $iDec Or $iDec = 0 Then Return $sRes
    $sTmp = StringLeft(StringRight($sX, $iDec - $iD), 1)
    $sRet = StringTrimRight($sRes, $iDec - $iD)
    If $sTmp >= 5 And $iD > 0 Then
        If $iNeg = 1 Then
            $sRet = _BigNum_Add($sRet, "-0." & StringFormat("%0" & String($iD) & "u", "1"))
        Else
            $sRet = _BigNum_Add($sRet, "0." & StringFormat("%0" & String($iD) & "u", "1"))
        EndIf
    ElseIf $sTmp >= 5 And $iD = 0 Then
        If $iNeg = 1 Then
            $sRet = _BigNum_Add($sRet, "-1")
        Else
            $sRet = _BigNum_Add($sRet, "1")
        EndIf
    Else
        If StringRight($sRet, 1) = "." Then $sRet = StringTrimRight($sRet, 1)
    EndIf
    Return $sRet
EndFunc   ;==>_BigNum_Round



; #FUNCTION# ;====================================================================================
;
; Name...........: _BigNum_Compare
; Description ...: Compares $sX $sY
; Syntax.........: _BigNum_Compare($sX, $sY)
; Parameters ....: $sX - StringNumber: Minus"-" Digits"0"..."9" Separator"." ("-1234567890.12345")
;                  $sY - StringNumber: Minus"-" Digits"0"..."9" Separator"." ("-1234567890.12345")
; Return values .: Success - Return:
;                  |0  - $sX and $sY are equal
;                  |1  - $sX is greater than $sY
;                  |-1 - $sX is less than $sY
;                  Failure - sets @error to 1 if $sX/$sY not valid StringNumber
; Author ........: Eukalyptus www.autoit.de
;
; ;===============================================================================================
Func _BigNum_Compare($sX, $sY)
    Local $iNeg = _BigNum_CheckNegative($sX, $sY)
    If $iNeg = 1 Then Return -1
    If $iNeg = 2 Then Return 1
    Local $iLnX = StringLen($sX), $iLnY = StringLen($sY)
    If $iNeg = 3 Then
        If $iLnX > $iLnY Then
            Return -1
        ElseIf $iLnX < $iLnY Then
            Return 1
        Else
            If $sX > $sY Then
                Return -1
            ElseIf $sX < $sY Then
                Return 1
            Else
                Return 0
            EndIf
        EndIf
    Else
        If $iLnX > $iLnY Then
            Return 1
        ElseIf $iLnX < $iLnY Then
            Return -1
        Else
            If $sX > $sY Then
                Return 1
            ElseIf $sX < $sY Then
                Return -1
            Else
                Return 0
            EndIf
        EndIf
    EndIf
EndFunc   ;==>_BigNum_Compare

Func _BigNum_Swap(ByRef $sX, ByRef $sY)
    Local $sSwap = $sX
    $sX = $sY
    $sY = $sSwap
    Return True
EndFunc   ;==>_BigNum_Swap




; #INTERNAL_USE_ONLY#============================================================================================================



#region Internal Functions
Func _BigNum_Div_DivisorGreater14($sX, $sY, ByRef $sM)
    $sM="0"
    If $sY="1" Then Return $sX
    If $sX = "0" Or $sY = "0" Or $sX = "" Or $sY = "" Then Return "0"
    If $BigNum_Debug Then 
        Local $BN_File=FileOpen(@ScriptDir & "\BigNum_Debug.txt",2), $BN_X=StringLen($sX)
        FileWrite($BN_File," " & $sX & " / " & $sY & " = " & @CRLF)
        FileWrite($BN_File," " & _BigNum_DS($BN_X+StringLen($sY)+3,"-") & @CRLF)
    EndIf
    Local $iLnY = StringLen($sY), $bRed = False
    Local $sRet = "", $sRem = StringLeft($sX, $iLnY), $sTmp = "", $sTm2 = "", $iCnt, $iLen = 1
    $sX = StringTrimLeft($sX, $iLnY)
    Do
        If _BigNum_DivComp($sRem, $sY) = -1 Then
            $sTmp = StringLeft($sX, 1)
            $sRem &= $sTmp
            $sX = StringTrimLeft($sX, 1)
            If StringLen($sTmp) > 0 Then $iLen += 1
        EndIf
        $sTmp = $sY
        $sTm2 = "0"
        If _BigNum_DivComp($sRem, $sY) >= 0 Then
            For $iCnt = 1 To 9
                $sTm2 = $sTmp
                $sTmp = _BigNum_DivAdd($sTmp, $sY)
                If _BigNum_DivComp($sRem, $sTmp) < 0 Then ExitLoop
            Next
        Else
            $iCnt = 0
        EndIf
        If $BigNum_Debug Then FileWrite($BN_File,_BigNum_DS($BN_X - StringLen($sX)-StringLen($sRem)+1) & $sRem & _BigNum_DS($BN_X+10-$iLen-$iLnY) & StringFormat("%0" & String($iLen) & "u", $iCnt) & @CRLF)
        If StringLen($sX) = 0 Then $bRed = True
        $sM = $sRem
        $sRem = _BigNum_DivSub($sRem, $sTm2)
        If $iCnt > 0 Then $sM = $sRem
        $sRet &= StringFormat("%0" & String($iLen) & "u", $iCnt)
        $iTrm = $iLnY - StringLen($sRem)
        $sTmp = StringLeft($sX, $iTrm)
        $sX = StringTrimLeft($sX, $iTrm)
        $iLen = StringLen($sTmp)
        $sRem &= $sTmp
    Until $bRed
    $sM = StringRegExpReplace($sM, "^0+([^0]|0$)", "\1", 1)
    If $BigNum_Debug Then 
        FileWrite($BN_File," " & _BigNum_DS($BN_X+9+StringRegExp($sRet, "^0+([^0]|0$)", "\1", 1)) & _BigNum_DS(StringLen(StringRegExpReplace($sRet, "^0+([^0]|0$)", "\1", 1)),"-") & @CRLF)
        FileWrite($BN_File," " & _BigNum_DS($BN_X+9+StringRegExp($sRet, "^0+([^0]|0$)", "\1", 1)) & StringRegExpReplace($sRet, "^0+([^0]|0$)", "\1", 1))
        FileClose($BN_File)
    EndIf
    Return StringRegExpReplace($sRet, "^0+([^0]|0$)", "\1", 1)
EndFunc   ;==>_BigNum_Div_DivisorGreater14

Func _BigNum_Div_DivisorMaxLen14($sX, $sY, ByRef $sM)
    $sM="0"
    If $sY="1" Then Return $sX
    If $sX = "0" Or $sY = "0" Or $sX = "" Or $sY = "" Then Return "0"
    If $BigNum_Debug Then 
        Local $BN_File=FileOpen(@ScriptDir & "\BigNum_Debug.txt",2), $BN_X=StringLen($sX)
        FileWrite($BN_File," " & $sX & " / " & $sY & " = " & @CRLF)
        FileWrite($BN_File," " & _BigNum_DS($BN_X+StringLen($sY)+3,"-") & @CRLF)
    EndIf
    Local $sRet = "", $iRem = StringLeft($sX, 15), $iTmp = 0, $iTrm = 6, $iLen
    $sX = StringTrimLeft($sX, 15)
    $iTmp = Floor($iRem / $sY)
    $sRet &= $iTmp
    If $BigNum_Debug Then FileWrite($BN_File," " & $iRem & _BigNum_DS(StringLen($sX)+10) & $iTmp & @CRLF)
    $iRem -= $iTmp * $sY
    While StringLen($sX) > 0
        $iTrm = 15 - StringLen($iRem)
        $iTmp = StringLeft($sX, $iTrm)
        $iLen = StringLen($iTmp)
        $iRem &= $iTmp
        $sX = StringTrimLeft($sX, $iTrm)
        $iTmp = Floor($iRem / $sY)
        $iTmp = StringRight("000000000000000" & $iTmp, $iLen)
        If $BigNum_Debug Then FileWrite($BN_File,_BigNum_DS($BN_X-StringLen($sX)+1-stringlen($iRem)) & $iRem & _BigNum_DS(StringLen($sX)+10+StringLen($sRet)) & $iTmp & @CRLF)
        $sRet &= $iTmp
        $iRem -= $iTmp * $sY
    WEnd
    $sM = String($iRem)
    If $BigNum_Debug Then 
        FileWrite($BN_File," " & _BigNum_DS($BN_X+10) & _BigNum_DS(StringLen(StringRegExpReplace($sRet, "^0+([^0]|0$)", "\1", 1)),"-") & @CRLF)
        FileWrite($BN_File," " & _BigNum_DS($BN_X+10) & StringRegExpReplace($sRet, "^0+([^0]|0$)", "\1", 1))
        FileClose($BN_File)
    EndIf
    Return StringRegExpReplace($sRet, "^0+([^0]|0$)", "\1", 1)
EndFunc   ;==>_BigNum_Div_DivisorMaxLen14

Func _BigNum_DivComp($sX, $sY)
    $sX = StringRegExpReplace($sX, "^0+([^0]|0$)", "\1", 1)
    $sY = StringRegExpReplace($sY, "^0+([^0]|0$)", "\1", 1)
    Local $iLnX = StringLen($sX), $iLnY = StringLen($sY)
    If $iLnX < $iLnY Then
        Return -1
    ElseIf $iLnX > $iLnY Then
        Return 1
    Else
        If $sX < $sY Then
            Return -1
        ElseIf $sX > $sY Then
            Return 1
        Else
            Return 0
        EndIf
    EndIf
EndFunc   ;==>_BigNum_DivComp

Func _BigNum_DivAdd($sX, $sY)
    Local $iTmp = StringLen($sX), $iLen = StringLen($sY), $iCar = 0, $sRet = ""
    If $iLen < $iTmp Then $iLen = $iTmp
    For $i = 1 To $iLen Step 18
        $iTmp = Int(StringRight($sX, 18)) + Int(StringRight($sY, 18)) + $iCar
        $sX = StringTrimRight($sX, 18)
        $sY = StringTrimRight($sY, 18)
        If ($iTmp > 999999999999999999) Then
            $sRet = StringRight($iTmp, 18) & $sRet
            $iCar = 1
        Else
            $iTmp = StringRight("000000000000000000" & $iTmp, 18)
            $sRet = $iTmp & $sRet
            $iCar = 0
        EndIf
    Next
    $sRet = StringRegExpReplace($iCar & $sRet, "^0+([^0]|0$)", "\1", 1)
    Return $sRet
EndFunc   ;==>_BigNum_DivAdd

Func _BigNum_DivSub($sX, $sY)
    Local $iTmp = StringLen($sX), $iLen = StringLen($sY), $iCar = 0, $sRet = ""
    If $iLen < $iTmp Then $iLen = $iTmp
    For $i = 1 To $iLen Step 18
        $iTmp = Int(StringRight($sX, 18)) - Int(StringRight($sY, 18)) - $iCar
        $sX = StringTrimRight($sX, 18)
        $sY = StringTrimRight($sY, 18)
        If $iTmp < 0 Then
            $iTmp = 1000000000000000000 + $iTmp
            $iCar = 1
        Else
            $iCar = 0
        EndIf
        $sRet = StringRight("0000000000000000000" & $iTmp, 18) & $sRet
    Next
    $sRet = StringRegExpReplace($iCar & $sRet, "^0+([^0]|0$)", "\1", 1)
    Return $sRet
EndFunc   ;==>_BigNum_DivSub

Func _BigNum_IsValid($sX, $sY)
    If StringRegExp($sX, "[^0-9.-]") <> 0 Or StringRegExp($sY, "[^0-9.-]") <> 0 Then Return True
    Return False
EndFunc   ;==>_BigNum_IsValid

Func _BigNum_InsertDecimalSeparator($sX, $iDec, $iD = 18)
    If $iD = 0 And $iDec = 0 Then Return $sX
    Local $sRet = StringRegExpReplace(StringRight(StringFormat("%0" & String($iDec) & "u", "") & $sX, $iDec), "0+$", "\1", 1)
    $sX = StringTrimRight($sX, $iDec)
    If $sX = "" Then $sX = "0"
    $sRet = StringLeft($sRet, $iD)
    If $sRet = "" Or $sRet = "0" Then Return $sX
    Return $sX & "." & $sRet
EndFunc   ;==>_BigNum_InsertDecimalSeparator

Func _BigNum_StringIsDecimal(ByRef $sX, ByRef $sY)
    If StringLeft($sX, 1) = "." Then $sX = "0" & $sX
    If StringLeft($sY, 1) = "." Then $sY = "0" & $sY
    Local $iPsX = StringInStr($sX, ".", 0, 1) - 1, $iPsY = StringInStr($sY, ".", 0, 1) - 1
    $sX = StringRegExpReplace($sX, "\D", "")
    $sY = StringRegExpReplace($sY, "\D", "")
    Local $iLnX = StringLen($sX), $iLnY = StringLen($sY)
    If $iPsX <= 0 Then $iPsX = $iLnX
    If $iPsY <= 0 Then $iPsY = $iLnY
    If $iLnX - $iPsX > $iLnY - $iPsY Then
        For $iCnt = $iLnY - $iPsY To $iLnX - $iPsX - 1
            $sY &= "0"
        Next
        Return $iLnX - $iPsX
    ElseIf $iLnX - $iPsX < $iLnY - $iPsY Then
        For $iCnt = $iLnX - $iPsX To $iLnY - $iPsY - 1
            $sX &= "0"
        Next
        Return $iLnY - $iPsY
    EndIf
    Return $iLnX - $iPsX
EndFunc   ;==>_BigNum_StringIsDecimal

Func _BigNum_CheckNegative(ByRef $sX, ByRef $sY)
    Local $bNgX = False, $bNgY = False
    While StringLeft($sX, 1) = "-"
        $bNgX = Not $bNgX
        $sX = StringTrimLeft($sX, 1)
    WEnd
    While StringLeft($sY, 1) = "-"
        $bNgY = Not $bNgY
        $sY = StringTrimLeft($sY, 1)
    WEnd
    $sX = StringRegExpReplace($sX, "^0+([^0]|0$)", "\1", 1)
    $sY = StringRegExpReplace($sY, "^0+([^0]|0$)", "\1", 1)
    If $sX = "" Then $sX = "0"
    If $sY = "" Then $sY = "0"
    If $bNgX = True And $bNgY = True Then
        Return 3
    ElseIf $bNgX = True And $bNgY = False Then
        Return 1
    ElseIf $bNgX = False And $bNgY = True Then
        Return 2
    Else
        Return 0
    EndIf
EndFunc   ;==>_BigNum_CheckNegative

Func _BigNum_DS($iC, $sS=" ")
    Local $sRet="", $iCnt
    For $iCnt=1 To $iC
        $sRet&=$sS
    Next
    Return $sRet
EndFunc
#endregion Internal Functions

Thanks for any help provided. Good nights.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...