#include-once
#include <array.au3>
;~ #cs
;============Example1.au3
Local $num = InputBox('叠加1-999(除含4和7)', '只能输入数字9', '999999999')
Local $result = ""
Local $i, $j
Local $timer = TimerInit()
For $i = 1 To 99
If Not StringRegExp($i, "4|7") Then
$j = $j + $i
EndIf
If $i = 9 Then
$one = $j
Else
$two = $j
EndIf
Next
$len = StringLen($num)
If $len < 2 Then
$result = $one
Else
$result = $two
EndIf
$out = ""
$pe = ""
For $i = 1 To $len - 2
For $j = 1 To $i - 1
$pe &= "0"
Next
$p = '80.' & $pe & '72' & $pe & '72' & $pe & '72' & $pe & '72' & $pe & '72' & $pe & '72' & $pe & '72' & $pe & '72' & $pe & '72' & $pe & '72' & $pe & '72' & $pe & '72'
$result = _MultiX($result, $p)
$pe = ""
Next
MsgBox(0, "耗时:" & TimerDiff($timer), "1-" & $num & " 相加的数是:" & _RoundX($result) & @CRLF & @CRLF & "未进行四舍五入前的值:" & $result)
;===============Example1.au3 end
;~ #ce
;===============Example2.au3
Dim $input = InputBox("", "输入测试数据"&@CRLF&"格式:数字1^次方", "214748.3647^20")
If $input == "" Then
MsgBox(0, "", "没有确认输入数据")
Exit
EndIf
$temp = StringSplit($input, '^')
$num = $temp[1]
$exp = $temp[2]
$result = _ExpX($num, $exp)
$e = StringInStr($result, ".") - 2
MsgBox(0, "超长精度幂运算", $num & '^' & $exp & '=' & $num ^ $exp & @CRLF & _
"超长精度结果:" & $result & @CRLF & "数据长度:" & StringLen($result) & " e = +" & $e)
$NewNum2 = StringMid($result, StringInStr($result, ".") - Random(5, 50), Random(50, 100))
$mulresult = _MultiX($num, $NewNum2)
$e = StringInStr($mulresult, ".") - 2
MsgBox(0, "超长精度乘法运算", $num & ' * ' & $NewNum2 & ' = ' & @CRLF & $num * $NewNum2 & @CRLF & _
"超长精度结果:" & $mulresult & @CRLF & "数据长度:" & StringLen($mulresult) & " e = +0" & $e)
$newNum1 = StringMid($mulresult, StringInStr($mulresult, ".") - Random(5, 10), Random(50, 100))
$NewNum2 = StringMid($result, StringInStr($result, ".") - Random(5, 10), Random(50, 100))
$subTraresult = _Subtra($newNum1, $NewNum2)
$e = StringInStr($subTraresult, ".") - 2
MsgBox(0, "超长精度减法运算", $newNum1 & ' - ' & $NewNum2 & ' = ' & @CRLF & $newNum1 - $NewNum2 & @CRLF & _
"超长精度结果:" & $subTraresult & @CRLF & "数据长度:" & StringLen($subTraresult) & " e = +0" & $e)
$newNum1 = StringMid($mulresult, StringInStr($mulresult, ".") - Random(5, 10), Random(50, 100))
$NewNum2 = StringMid($result, StringInStr($result, ".") - Random(5, 10), Random(50, 100))
$Plusresult = _PlusX($newNum1, $NewNum2)
$e = StringInStr($Plusresult, ".") - 2
MsgBox(0, "超长精度加法运算", $newNum1 & ' + ' & $NewNum2 & ' = ' & @CRLF & $newNum1 + $NewNum2 & @CRLF & _
"超长精度结果:" & $Plusresult & @CRLF & "数据长度:" & StringLen($Plusresult) & " e = +0" & $e)
;==================Example2.au3 end
Func _MultiX($num1, $num2)
Local $result[10000], $point
$pointSpace1 = StringInStr($num1, ".")
$pointSpace2 = StringInStr($num2, ".")
If $pointSpace1 Then $point += StringLen($num1) - $pointSpace1
If $pointSpace2 Then $point += StringLen($num2) - $pointSpace2
$num1 = StringReplace($num1, ".", "")
$num2 = StringReplace($num2, ".", "")
$aNum = StringSplit($num1, "")
_ArrayReverse($aNum, 1, UBound($aNum) - 1)
_ArrayDelete($aNum, 0)
If $result[0] == "" Then
$bNum = StringSplit($num2, "")
_ArrayReverse($bNum, 1, UBound($bNum) - 1)
_ArrayDelete($bNum, 0)
Else
ReDim $bNum[1]
For $k = 0 To UBound($result) - 1
If $result[$k] == "" Then ExitLoop
_ArrayAdd($bNum, $result[$k])
$result[$k] = ""
Next
_ArrayDelete($bNum, 0)
EndIf
For $i = 0 To UBound($aNum) - 1
For $j = 0 To UBound($bNum) - 1
$cur = $i + $j
$result[$cur] += $aNum[$i] * $bNum[$j]
If $result[$cur] >= 10 Then
$temp = Mod($result[$cur], 10)
$result[$cur + 1] += Int($result[$cur] / 10)
$result[$cur] = $temp
EndIf
Next
Next
_ArrayReverse($result, 0, UBound($result) - 1)
$sResult = StringReplace(_ArrayToString($result), '|', "")
$temp = StringRight($sResult, $point)
If $temp Then $sResult = StringTrimRight($sResult, $point) & '.' & $temp
Return $sResult
EndFunc ;==>_MultiX
Func _ExpX($num, $e = 2)
Local $sResult
$sResult = $num
If Not $e Then $sResult = 0
While $e >= 2
If $sResult Then
$sResult = _MultiX($num, $sResult)
EndIf
$e -= 1
WEnd
Return $sResult
EndFunc ;==>_ExpX
Func __plusPoint($num1, $num2)
Local $result[10000], $out = 0
$temp = ""
If StringInStr($num1, ".") Then $temp = StringRegExpReplace($num1, ".*\.(\d+)", '$1')
$point1 = $temp
$temp = ""
If StringInStr($num2, ".") Then $temp = StringRegExpReplace($num2, ".*\.(\d+)", '$1')
$point2 = $temp
If Not $point1 Or Not $point2 Then Return $point1 + $point2
$aNum = StringSplit($point1, "")
$bNum = StringSplit($point2, "")
_ArrayDelete($aNum, 0)
_ArrayDelete($bNum, 0)
$aSize = UBound($aNum) - 1
$bSize = UBound($bNum) - 1
$maxSize = $aSize
If $bSize > $aSize Then $maxSize = $bSize
$i = 0
While 1
$temp1 = ""
$temp2 = ""
If $i <= $aSize Then $temp1 = $aNum[$i]
If $i <= $bSize Then $temp2 = $bNum[$i]
$temp = $temp1 + $temp2
If $temp >= 10 Then
$result[$i] = $temp - 10
If $i == 0 Then
$out = 1
Else
$result[$i - 1] += 1
$k = $i - 1
While $result[$k] >= 10
$result[$k] = $result[$k] - 10
$result[$k - 1] += 1
$k -= 1
If $k == 0 Then $out += 1
WEnd
EndIf
Else
$result[$i] += $temp
$k = $i
While $result[$k] >= 10
$result[$k] = $result[$k] - 10
$result[$k - 1] += 1
$k -= 1
If $k == 0 Then $out += 1
WEnd
EndIf
If $i == $maxSize Then ExitLoop
$i += 1
WEnd
$sResult = $out & '.' & StringReplace(_ArrayToString($result), '|', "")
Return $sResult
EndFunc ;==>__plusPoint
Func _PlusX($num1, $num2)
$pResult = __plusPoint($num1, $num2)
$pInt = StringLeft($pResult, 1)
$pResult = StringTrimLeft($pResult, 1)
Local $result[10000]
$result[0] = $pInt
$Integer1 = StringRegExpReplace($num1, '(\d+)\..*', '$1')
$Integer2 = StringRegExpReplace($num2, '(\d+)\..*', '$1')
$aNum = StringSplit($Integer1, "")
$bNum = StringSplit($Integer2, "")
_ArrayReverse($aNum, 1, UBound($aNum) - 1)
_ArrayDelete($aNum, 0)
_ArrayReverse($bNum, 1, UBound($bNum) - 1)
_ArrayDelete($bNum, 0)
$aSize = UBound($aNum) - 1
$bSize = UBound($bNum) - 1
$maxSize = $aSize
If $bSize > $aSize Then $maxSize = $bSize
$i = 0
While 1
$temp1 = ""
$temp2 = ""
If $i <= $aSize Then $temp1 = $aNum[$i]
If $i <= $bSize Then $temp2 = $bNum[$i]
$temp = $temp1 + $temp2
If $temp1 + $temp2 >= 10 Then
$result[$i] += $temp - 10
$result[$i + 1] += 1
$k = $i + 1
While $result[$k] >= 10
$result[$k] = $result[$k] - 10
$result[$k + 1] += 1
$k += 1
WEnd
Else
$result[$i] += $temp
$k = $i
While $result[$k] >= 10
$result[$k] = $result[$k] - 10
$result[$k + 1] += 1
$k += 1
WEnd
EndIf
If $i == $maxSize Then ExitLoop
$i += 1
WEnd
_ArrayReverse($result, 0, UBound($result) - 1)
$integerResult = StringReplace(_ArrayToString($result), '|', "")
Return $integerResult & $pResult
EndFunc ;==>_PlusX
Func _Subtra($num1, $num2)
Local $result[10000], $Symbol = "", $pInt = 0, $pResult = ""
If Number($num1) < Number($num2) Then
$temp = $num1
$num1 = $num2
$num2 = $temp
$Symbol = "-"
EndIf
$subResult = __SubtraPoint($num1, $num2)
If $subResult <> "" Then
$pInt = StringRegExpReplace($subResult, '(.*)\..*', '$1')
$pResult = StringRegExpReplace($subResult, '.*\.(.*)', '$1')
EndIf
Local $result[10000]
$Integer1 = StringRegExpReplace($num1, '(\d+)\..*', '$1')
$Integer2 = StringRegExpReplace($num2, '(\d+)\..*', '$1')
$aNum = StringSplit($Integer1, "")
$bNum = StringSplit($Integer2, "")
_ArrayReverse($aNum, 1, UBound($aNum) - 1)
_ArrayDelete($aNum, 0)
_ArrayReverse($bNum, 1, UBound($bNum) - 1)
_ArrayDelete($bNum, 0)
$result[0] = $pInt
$aSize = UBound($aNum) - 1
$bSize = UBound($bNum) - 1
$maxSize = $aSize
If $bSize > $aSize Then $maxSize = $bSize
$i = 0
While 1
$temp1 = ""
$temp2 = ""
If $i <= $aSize Then $temp1 = $aNum[$i]
If $i <= $bSize Then $temp2 = $bNum[$i]
$temp = $temp1 - $temp2
If $temp < 0 Then
$result[$i] += $temp + 10
$result[$i + 1] -= 1
Else
$result[$i] += $temp
If $result[$i] < 0 Then
$result[$i] = $result[$i] + 10
$result[$i + 1] -= 1
EndIf
EndIf
If $i == $maxSize Then ExitLoop
$i += 1
WEnd
_ArrayReverse($result, 0, UBound($result) - 1)
$integerResult = StringReplace(_ArrayToString($result), '|', "")
Return $Symbol & $integerResult & "." & $pResult
EndFunc ;==>_Subtra
Func __SubtraPoint($num1, $num2)
Local $result[10000], $out = 0
$temp = ""
If StringInStr($num1, ".") Then $temp = StringRegExpReplace($num1, ".*\.(\d+)", '$1')
$point1 = $temp
$temp = ""
If StringInStr($num2, ".") Then $temp = StringRegExpReplace($num2, ".*\.(\d+)", '$1')
$point2 = $temp
If Not $point2 Then Return $point1
$aNum = StringSplit($point1, "")
$bNum = StringSplit($point2, "")
_ArrayDelete($aNum, 0)
_ArrayDelete($bNum, 0)
$aSize = UBound($aNum) - 1
$bSize = UBound($bNum) - 1
$maxSize = $aSize
If $bSize > $aSize Then $maxSize = $bSize
$i = 0
While 1
$temp1 = ""
$temp2 = ""
If $i <= $aSize Then $temp1 = $aNum[$i]
If $i <= $bSize Then $temp2 = $bNum[$i]
$temp = $temp1 - $temp2
If $temp < 0 Then
$result[$i] += $temp + 10
If $i == 0 Then
$out = -1
Else
$result[$i - 1] -= 1
$k = $i - 1
While $result[$k] < 0
$result[$k] = $result[$k] + 10
$result[$k - 1] -= 1
$k -= 1
WEnd
EndIf
Else
$result[$i] += $temp
If $result[$i] < 0 Then
$result[$i] = $result[$i] + 10
$result[$i - 1] -= 1
$k = $i - 1
While $result[$k] < 0
$result[$k] = $result[$k] + 10
$result[$k - 1] -= 1
$k -= 1
WEnd
EndIf
EndIf
If $i == $maxSize Then ExitLoop
$i += 1
WEnd
$sResult = $out & '.' & StringReplace(_ArrayToString($result), '|', "")
Return $sResult
EndFunc ;==>__SubtraPoint
Func _RoundX($num, $n = 0)
$point = StringInStr($num, ".")
If $point <= 0 Then Return $num
$sResult = StringLeft($num, $point + $n + 1)
$aResult = StringSplit($sResult, "")
_ArrayDelete($aResult, 0)
$arrayCur = UBound($aResult) - 1
If $aResult[$arrayCur] >= 5 Then
If $aResult[$arrayCur - 1] <> "." Then
$aResult[$arrayCur - 1] += 1
$aResult[$arrayCur] = 0
$arrayCur -= 1
Else
$aResult[$arrayCur - 2] += 1
$aResult[$arrayCur] = 0
$arrayCur -= 2
EndIf
Else
_ArrayDelete($aResult, $arrayCur)
Return
EndIf
While $arrayCur
If $aResult[$arrayCur] >= 10 Then
$aResult[$arrayCur] -= 10
If $aResult[$arrayCur - 1] == "." Then $arrayCur -= 1
$aResult[$arrayCur - 1] += 1
EndIf
$arrayCur -= 1
WEnd
_ArrayDelete($aResult, UBound($aResult))
If $n == 0 Then _ArrayDelete($aResult, UBound($aResult))
$sResult = StringReplace(_ArrayToString($aResult), '|', "")
Return $sResult
EndFunc ;==>_RoundX