ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 Excel Home精品图文教程库
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
300集Office 2010微视频教程 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 6018|回复: 11

[原创] 超大整数的计算(会有更快的~)

[复制链接]

TA的精华主题

TA的得分主题

发表于 2013-10-22 14:41 | 显示全部楼层 |阅读模式
本帖已被收录到知识树中,索引项:其他结构和算法
本帖最后由 lee1892 于 2013-10-23 10:16 编辑

发现自己受下面提到的那个帖子影响,居然用文本来计算!实在是太傻了!
Sigh~,这个附件就不删了,权当鞭策了。
===================================================================
所谓超大整数,指数字的范围远远超过VBA提供的数据类型可计算的限制,其数字的位数为Long。

对于天文数字和高精度值i的计算的需求而言,超大整数的计算是有其现实意义的。

论坛里貌似只有这个贴子提供了代码:天文数字及高精度数字运算
但我测试了一下,其效率是非常低的,而且用起来也很不方便。

附件是一个超大整数的类,数字本身以字符串存储,目前支持:
1、超大数 + LONG
2、超大数 + 超大数
3、超大数 - LONG
4、超大数 - 超大数
5、超大数 * LONG
6、超大数 * 超大数
并且支持负数
除法未完成,计划支持获得商和余数。

Sheet1 中提供了测试代码,以验证其正确性以及速度,在我机器上测试速度如下(其中加减法为两个千万位的超大数,乘法为千万位的超大数和千万内的数):
[code=vb]' GREAT! No error found!!!
' Testing Huge Integer in length: 10,000,000 ...
' Huge Integer Plus Used: 3.250s
' Huge Integer Subtract Used: 3.297s
' Huge Integer Multiply Used: 33.297s[/code]

测试代码如下:
[code=vb]Sub TestHugeIntegerClass()
    Dim hiNum As New HugeInt_LEE1892
    Dim i&, nNumA&, nNumB&, nRes&, sRes$, bFlag As Boolean
    bFlag = True
    For i = 1 To 1000
        nNumA = Int(2000000 * Rnd - 1000000)
        nNumB = Int(2000 * Rnd - 1000)
        With hiNum
            .Number = CStr(nNumA)
            
            nRes = nNumA + nNumB
            sRes = .PlusLong(nNumB)
            If CStr(nRes) <> sRes Then bFlag = False: Debug.Print nNumA; "+L"; nNumB; nRes; "NOT "; sRes
            sRes = .PlusHugeInt(CStr(nNumB))
            If CStr(nRes) <> sRes Then bFlag = False: Debug.Print nNumA; "+S"; nNumB; nRes; "NOT "; sRes
            
            nRes = nNumA - nNumB
            sRes = .SubtractLong(nNumB)
            If CStr(nRes) <> sRes Then bFlag = False: Debug.Print nNumA; "-L"; nNumB; nRes; "NOT "; sRes
            sRes = .SubtractHugeInt(CStr(nNumB))
            If CStr(nRes) <> sRes Then bFlag = False: Debug.Print nNumA; "-S"; nNumB; nRes; "NOT "; sRes
            
            nRes = nNumA * nNumB
            sRes = .MultiplyLong(nNumB)
            If CStr(nRes) <> sRes Then bFlag = False: Debug.Print nNumA; "*L"; nNumB; nRes; "NOT "; sRes
            sRes = .MultiplyHugeInt(CStr(nNumB))
            If CStr(nRes) <> sRes Then bFlag = False: Debug.Print nNumA; "*S"; nNumB; nRes; "NOT "; sRes
            
        End With
    Next
    If bFlag Then Debug.Print "GREAT! No error found!!!"
   
    Dim aNumA() As Byte, aNumB() As Byte, sNumA$, sNumB$, t#, nCnt&
   
    nCnt = 10 ^ 7
    ReDim aNumA(0 To nCnt * 2 - 1)
    ReDim aNumB(0 To nCnt * 2 - 1)
    For i = 1 To nCnt
        aNumA((i - 1) * 2) = Int(Rnd * 10) + 48
        aNumB((i - 1) * 2) = Int(Rnd * 10) + 48
    Next
    With hiNum
        .Number = aNumA
        sNumB = aNumB
        
        Debug.Print "Testing Huge Integer in length: " & Format(.Length, "#,##0") & " ..."
        
        t = Timer
        sNumA = .PlusHugeInt(sNumB)
        Debug.Print "Huge Integer Plus Used: " & Format(Timer - t, "0.000s")
        
        t = Timer
        sNumA = .SubtractHugeInt(sNumB)
        Debug.Print "Huge Integer Subtract Used: " & Format(Timer - t, "0.000s")
        
        nNumB = Int(nCnt * Rnd)
        t = Timer
        sNumA = .MultiplyLong(nNumB)
        Debug.Print "Huge Integer Multiply Used: " & Format(Timer - t, "0.000s")
    End With
    Set hiNum = Nothing
    Erase aNumA: Erase aNumB
End Sub[/code]

类代码可以直接编译为DLL,速度会更快。

测试环境:WinXP 32位,Excel 2003

如果有人有更快的实现,欢迎讨论。

HugeInteger_CLASS_Lee1892_v0.1.rar

30.28 KB, 下载次数: 118

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2013-10-22 14:46 | 显示全部楼层
{:soso_e122:}太厉害了,拜读一下

TA的精华主题

TA的得分主题

 楼主| 发表于 2013-10-22 14:49 | 显示全部楼层

TA的精华主题

TA的得分主题

 楼主| 发表于 2013-10-22 22:58 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
本帖最后由 lee1892 于 2013-10-22 23:01 编辑

联想到基数排序算法,我想我有办法大幅提高超大数的计算速度了,尤其是乘法
{:soso_e113:}

TA的精华主题

TA的得分主题

发表于 2013-10-22 22:59 | 显示全部楼层
下载试一下,顶一个{:soso_e179:}

TA的精华主题

TA的得分主题

发表于 2013-10-22 23:30 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2013-11-4 23:15 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
关注一下。

我把这一类数叫做【超长数位数值】简称【超长数】,或者叫做【文本数值】(因为超长数位的数值只能用文本格式显示)
实际使用应该不局限于整数,小数、正负数都应该作为计算对象。


我写的代码是把数值切割、然后用CDec()转换后进行计算的。

因为,CDec()函数的取值范围比较大: +/-79,228,162,514,264,337,593,543,950,335

这样用CDec数值进行直接计算,速度快很多。

TA的精华主题

TA的得分主题

发表于 2013-11-4 23:51 | 显示全部楼层
测试乘法可以用阶乘……比如 10000的阶乘计算次数就不少了。虽然结果只有 35660位。

不过楼主一下子就计算【长度千万数位】的数值,是比较恐怖的……应该远远超过实用的需求了。


TA的精华主题

TA的得分主题

 楼主| 发表于 2013-11-5 08:44 | 显示全部楼层
香川群子 发表于 2013-11-4 23:51
测试乘法可以用阶乘……比如 10000的阶乘计算次数就不少了。虽然结果只有 35660位。

不过楼主一下子就计 ...

一楼使用的文本计算是个笨办法,效率低下。

TA的精华主题

TA的得分主题

发表于 2013-11-5 13:01 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
天文数字及高精度数字运算

中介绍怎么用的,但楼主的不知怎么用的。有动画或者附件(自定义函数)之类的?
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

关闭

最新热点上一条 /1 下一条

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-4-20 00:00 , Processed in 0.049428 second(s), 11 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

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