ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

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

[分享] Excel中实现长整数加法和乘法运算的一种公式写法

[复制链接]

TA的精华主题

TA的得分主题

发表于 2023-10-26 17:01 | 显示全部楼层 |阅读模式
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
本帖最后由 shaowu459 于 2023-10-26 17:24 编辑

在Excel中,由于数据精度的问题,超长的整数不能在单元格中直接通过简单加减乘除运算得到正确结果。目前,在Microsoft 365中,可以在Excel中使用Python来直接实现一定长度整数的四则运算,但如果还没有Python功能的用户,只能通过函数公式计算和模拟这种运算。本帖主要介绍使用REDUCE函数来模拟小学生列竖式的方法实现长整数加法和乘法运算的一种公式写法。

特别说明:
关于大整数的乘法运算,历史上数学家们一直在优化并提出更快的算法,例如Karatsuba算法、Schönhage-Strassen算法等,但是这些算法里说的大整数,指的是类似10亿位整数这种数量级,本帖的公式示例数据整数长度乘法在百位左右,加法在几百位左右,仅仅用于介绍公式写法。


图片.jpg

大数字乘积和求和-超人方案.rar

22.12 KB, 下载次数: 38

评分

7

查看全部评分

TA的精华主题

TA的得分主题

发表于 2023-10-26 17:07 | 显示全部楼层
话题太深奥,文化不够看不懂

点评

就是列竖式计算,很简单。只不过你wps用不了:)  发表于 2023-10-26 17:25

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-10-26 17:14 | 显示全部楼层
本帖最后由 shaowu459 于 2023-10-26 17:26 编辑

首先介绍长整数加法实现的公式。

本帖使用的方法是利用REDUCE函数的x来实现进位的记忆和结果字符串的生成,在运算过程中一直需要维护如下结构的x:
图片.png

在x顶部记录加法结果的字符串,在x底部记录当前两个长整数对应位置数字加和的结果是否进位,因为两个个位数相加,最多只能进1,所以是否进位可以用逻辑值TRUE或FALSE代表。

长整数加法竖式运算和短整数竖式运算方法是一样的,因此我们以9876+415这个短的加法为例介绍公式运算逻辑。

第一步:两个数字个位数相加结果是11,在x顶部将11的个位数和x的初始值""连接起来。
图片.png

第二步:因为11大于9,所以在x底部记录TRUE,也就是需要进位。
图片.png

第三步:计算十位数字之和7+1=8,因为个位相加需要进位,所以再用8加上x底部的TRUE,得到9。提取9的个位数和当前x顶端的1连接,得到91。
图片.png

第四步:判断,因为9<10,所以不进位,x底端更新为FALSE。
图片.png

以此类推,直到每一个对应位置运算完毕,x顶端记录的值10291就是需要的计算结果。为了防止最高位加和进位不被记录的情况,我们可以在两个加数之前加上一个0。如下面的示例:
图片.png

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-10-26 17:19 | 显示全部楼层
加法公式的一种写法如下:
  1. =LET(t,@REDUCE("",SEQUENCE(1+MAX(LEN(B11:C11))),LAMBDA(x,y,LET(s,SUM(--LEFT(RIGHT(0&B11:C11,y)),N(TAKE(x,-1))),VSTACK(RIGHT(s)&@x,s>9)))),--LEFT(t,9)&MID(t,10,999))
复制代码
图片.jpg
图片.png


TA的精华主题

TA的得分主题

 楼主| 发表于 2023-10-26 17:23 | 显示全部楼层
上楼加法实现公式简要说明如下:

=LET(
    t, @REDUCE(            @提取x最上端的结果字符串
        "",                初始值设定为空字符串
        SEQUENCE(1 + MAX(LEN(B11:C11))),   生成1到两个数字最长长度+1的序列,之所以+1是因为在每个数字之前要加一个0
        LAMBDA(x, y,
            LET(
                s, SUM(
                    --LEFT(RIGHT(0 & B11:C11, y)),    从最末位开始,分别提取两个数字对应位置数字加和
                    N(TAKE(x, -1))                    也要加上上次运算需要进位的1或者不进位的0
                ),
                VSTACK(RIGHT(s) & @x, s > 9)          提取上一步的运算结果的个位数,连接x顶端的字符串;同时判断是否进位,放在x底端
            )
        )
    ),
    --LEFT(t, 9) & MID(t, 10, 999)         因为运算结果可能有前导0,所以将前导0去掉。可以有不同写法,这里和乘法公式保持一致。
)

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-10-26 19:03 | 显示全部楼层
在介绍乘法计算公式之前,以876*345为例先看一下竖式计算乘法的方式:
图片.png

上面的竖式中:876先乘以5得到4380,然后876乘以4得到3504(错位,实际数值是35040),876乘以3得到2628(错位,实际数值是262800),最后上述3个数字再相加即可。其中,876需要和第二个数字中的每个位置的数字相乘,得到的大整数结果再求和可以用之前提到的大整数求和的公式。


TA的精华主题

TA的得分主题

 楼主| 发表于 2023-10-26 19:13 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
在计算第一步乘法,也就是第一个数字和第二个数字每一位相乘的时候,仍然可以使用REDUCE函数来实现,x的第一个元素记录结果字符串,第二个元素记录进位的数值。


仍以上面的876*345数据为例:

第一步:依次用876的个位、十位、百位分别乘以5,得到的结果加上x中记录的上步运算的进位值,得到的结果个位数和x顶端的字符连接起来,更新x的底端值为这次计算完毕后需要进位的数值。最终得到4380

图片.png

第二步:依次用876的个位、十位、百位分别乘以4,最终得到3504
图片.png

第三步:将4380和35040用大数加法公式加和,最终得到:39420
第四步:依次用876的个位、十位、百位分别乘以3,得到262800,再和39420加和,得到最终结果:302220。

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-10-26 19:14 | 显示全部楼层
有了以上的分析,我们使用以下公式可以计算大整数的乘法(其中调用大数加法运算):
  1. =LET(p,0&B3,q,0&C3,v,REDUCE(0,SEQUENCE(LEN(q)),LAMBDA(x,y,加法(HSTACK(x,@REDUCE("",MID(p,LEN(p)-SEQUENCE(LEN(p))+1,1),LAMBDA(m,n,LET(s,n*LEFT(RIGHT(q,y))+N(TAKE(m,-1)),VSTACK(RIGHT(s)&@m,INT(s/10)))))&REPT(0,y-1))))),--LEFT(v,9)&MID(v,10,999))
复制代码
图片.jpg
图片.png


TA的精华主题

TA的得分主题

 楼主| 发表于 2023-10-26 19:20 | 显示全部楼层
公式简要说明如下:
=LET(
    p, 0 & B3,  加上前置的0
    q, 0 & C3,  加上前置的0
    v, REDUCE(
        0,      初始值设为0
        SEQUENCE(LEN(q)),    遍历q的每个数字,分别和p的数字相乘
        LAMBDA(x, y,
            加法(          调用大整数加法运算,将每步运算结果相加
                HSTACK(
                    x,     加法的第一个数,REDUCE函数返回加法的第二个数
                    @REDUCE(
                        "",    初始值设置为空文本
                        MID(p, LEN(p) - SEQUENCE(LEN(p)) + 1, 1),    从个位开始提取p中的每个数字
                        LAMBDA(m, n,
                            LET(
                                s, n * LEFT(RIGHT(q, y)) + N(TAKE(m, -1)),    p中的每个数字乘以q中的数字+上一步进位的值
                                VSTACK(RIGHT(s) & @m, INT(s / 10))     取s的个位和m顶端的字符串连接,更新m的底端数为进位的值
                            )
                        )
                    ) & REPT(0, y - 1)   每运算一次,得到的结果后面加一个0
                )
            )
        )
    ),
    --LEFT(v, 9) & MID(v, 10, 999)    去掉最终结果中的前导0
)

TA的精华主题

TA的得分主题

发表于 2023-10-29 06:25 | 显示全部楼层
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

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

GMT+8, 2024-11-15 01:56 , Processed in 0.049805 second(s), 12 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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