找回密码
 加入
搜索
楼主: psp7456

[效率算法] [已解决]求从1加到999999999的高效算法

 火... [复制链接]
发表于 2010-8-3 23:23:39 | 显示全部楼层
回复 30# C.L
问题是这个倍数是怎么得出来的呢?请指教
 楼主| 发表于 2010-8-3 23:29:48 | 显示全部楼层
回复 30# 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
发表于 2010-8-3 23:37:21 | 显示全部楼层
原来是这个规律,你观察得太仔细了。
 楼主| 发表于 2010-8-3 23:37:58 | 显示全部楼层
回复 33# C.L


明白了,确实高明。

正常计算的话到了这么高的数位,精度早就丢失了。
 楼主| 发表于 2010-8-4 00:28:12 | 显示全部楼层
AU的计算效率还是比不上delphi啊
发表于 2010-8-4 00:29:15 | 显示全部楼层
回复 33# C.L
多谢指教,看了半天终于开窍了。谢谢
发表于 2010-8-5 09:59:42 | 显示全部楼层
看来还要数学好才搞得定
发表于 2010-8-6 17:53:16 | 显示全部楼层
MSGBOX(0,0,63380593714397184)
好吧 我承认我是灌水的
发表于 2010-8-7 14:23:50 | 显示全部楼层
这算来有用么?
发表于 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[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)
        $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

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

×
发表于 2010-8-10 03:55:53 | 显示全部楼层
好强大啊
发表于 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)
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2024-5-13 16:08 , Processed in 0.072200 second(s), 14 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表