3mile
发表于 2010-8-3 23:23:39
回复 30# C.L
问题是这个倍数是怎么得出来的呢?请指教
psp7456
发表于 2010-8-3 23:29:48
回复 30# C.L
递归?
C.L
发表于 2010-8-3 23:35:16
回复 31# 3mile
我用的是反推法,你运行下面这段代码,输入99999 看看结果,我的这个倍数就是这样得来的:
local $num = InputBox ('叠加1-999*','只能输入数字9','')
Local $out = "",$old = ""
For $i=StringLen($num) To 1 Step -1
$number = StringLeft ($num,$i)
$result = plus ($number)
If Not $old Then $old = $result
If Not ($old == $result) Then $out &= $old / $result & @CRLF
$old = $result
Next
MsgBox (0,$num,$out)
Func plus ($num)
Local $result = ""
local $i,$j
Local $timer = TimerInit ()
for $i=1 to $num
if Not stringregexp($i,"4|7") then
$j=$j+$i
endif
next
Return ($j)
EndFunc
ebhb
发表于 2010-8-3 23:37:21
原来是这个规律,你观察得太仔细了。
psp7456
发表于 2010-8-3 23:37:58
回复 33# C.L
明白了,确实高明。
正常计算的话到了这么高的数位,精度早就丢失了。
psp7456
发表于 2010-8-4 00:28:12
AU的计算效率还是比不上delphi啊{:1_588:}
3mile
发表于 2010-8-4 00:29:15
回复 33# C.L
多谢指教,看了半天终于开窍了。谢谢
4216730
发表于 2010-8-5 09:59:42
看来还要数学好才搞得定
大绯狼
发表于 2010-8-6 17:53:16
MSGBOX(0,0,63380593714397184)好吧 我承认我是灌水的
lixiaolong
发表于 2010-8-7 14:23:50
这算来有用么?
C.L
发表于 2010-8-9 14:17:12
回复 1# psp7456
解法应该没有问题,我一直在考虑这个解法为什么会不精确,后来终于找到了问题所在:
是AU3的乘法不知原种原因(自动截去?位小数后的数?)自动的四舍五入造成了精度不够准确
想了一个解决的办法,自写高精度的乘法运算来解决
下面代码中的 "_MultiX($num1, $num2)为$num1*$num2的函数,理论上位数可以精确到一万位。
先上个图:
代码:#include <array.au3>
Local $num = InputBox('叠加1-999*', '只能输入数字9', '')
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)
Func _MultiX($num1, $num2) ;高精度乘法运算,位数精确到10000位
Local $result, $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 == "" Then
$bNum = StringSplit($num2, "")
_ArrayReverse($bNum, 1, UBound($bNum) - 1)
_ArrayDelete($bNum, 0)
Else
ReDim $bNum
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)
$sResult = StringTrimRight($sResult, $point) & '.' & $temp
Return $sResult
EndFunc ;==>_MultiX
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
haodd
发表于 2010-8-10 03:55:53
好强大啊 {:face (332):}
ebhb
发表于 2010-8-23 18:56:29
我来发一个算法,比C.L的快100倍。
Local $num = InputBox('叠加1-999*', '只能输入数字9', '')
Local $i
Local $timer = TimerInit()
$len = StringLen($num)
$s=0
$i=0
While $i<$len
$s=$s*80+8^$i*34
$i=$i+1
WEnd
MsgBox(0, "耗时:" & TimerDiff($timer), "1-" & $num & " 相加的数是:" &$s)