sql中排序序号_SQL 和 SPL 的有序运算对比

【摘要】
有序运算是指按照一定的次序对有序集合的成员进行计算。SQL 和 SPL 是大家比较熟悉的程序语言,本文将探讨对于有序运算问题,这两种语言的解决方案和基本原理。如何简便快捷的处理有序运算,这里为你全程解析,并提供 SQL 和 SPL 示例代码。SQL 和 SPL 的有序运算对比

使用过 SQL 或 SPL 的朋友对计算字段都不会陌生,比如 firstname+lastname,year(birthday),这些计算字段属于行内计算。不管表达式里用到的是单个字段,还是多个字段,使用的数据都在当前记录行内。有行内计算,对应的也就有跨行计算,如:第一名和第二名的差距;从 1 月到当前月份累计的销售额。按照成绩有序,才会有第一名、第二名的说法,累计操作同样基于有序数据,从第几个累加到第几个,这些基于有序集合的计算,就属于有序计算。行内计算关心的是每条数据自身的情况,而跨行的有序计算则关心有序数据的变化情况。

一.相邻记录引用

简单常见的有序计算是相邻记录引用,也就是在计算中要引用某种次序下的相邻记录。比如下面这些问题:

1、 股价每天的涨幅是多少(比上期)

按日期排序时,引用上一天的股价。

2、 前一天 + 当天 + 后一天的平均股价是多少(移动平均)

按日期排序时,引用前后两天的股价。

3、 多支股票数据,计算每支股票内的每日涨幅(分组内的比上期)

按股票分组,组内按日期排序,引用上一天股价。

接下来通过这几个例子研究下 SQL 如何实现这类有序计算。

1. SQL的解决方案

早期 SQL 的解决方案

早期的 SQL 没有窗口函数,引用相邻记录的方法是用 JOIN 把相邻记录拼到同一行。

问题 1 写出来是这样的:

SELECT day, curr.price/pre.price rate

FROM (

SELECT day, price, rownum row1

FROM tbl ORDER BY day ASC) curr

LEFT JOIN (

SELECT day, price, rownum row2

FROM tbl ORDER BY day ASC) pre

ON curr.row1=pre.row2+1

即将本表和本表做 JOIN,把前一天和当天作为连接条件,这样即可将前一天的股价和当天股价连接到同一行中,再用行内计算得到涨幅。一个很简单的问题必须使用子查询才能解决。

再看问题 2,计算股价的移动平均,(前一天 + 当天 + 后一天)/3,同样是使用 JOIN 实现:

SELECT day, (curr.price+pre.price+after.price)/3 movingAvg

FROM (

SELECT day, price, rownum row1

FROM tbl ORDER BY day ASC) curr

LEFT JOIN (

SELECT day, price, rownum row2

FROM tbl ORDER BY day ASC) pre

ON curr.row1=pre.row2+1

LEFT JOIN (

SELECT day, price, rownum row3

FROM tbl ORDER BY day ASC) after

ON curr.row1=after.row3-1

多取一天,就多 JOIN 一个子查询,试想,如果要计算前 10 天 ~ 后 10 天的移动平均,那需要写 20 个 JOIN,这种语句能写死人。

再看更复杂一些的问题 3,股价表里有多支股票时,增加 code 字段区分不同的股票,那它的涨幅就要限定在某支股票的分组内:

SELECT code, day ,currPrice/prePrice rate

FROM(

SELECT code, day, curr.price currPrice, pre.price prePrice

FROM (

SELECT code, day, price, rownum row1

FROM tbl ORDER BY code, day ASC) curr

LEFT JOIN (

SELECT code, day, price, rownum row2

FROM tbl ORDER BY code, day ASC) pre

ON curr.row1=pre.row2+1 AND curr.code=pre.code

)

这里着重看两个地方:单表排序时,一定要增加股票代码,形成组合排序 code,day,code 还必须要在前面,这不难理解,先把一支股票的数据放在一起,然后这支股票组内数据再按照日期排序;数据排序好了还不算完,连接条件里也要加上股票代码相等,否则两个相邻的不同股票数据挨着,也会计算涨幅,但这是没意义的脏数据。

引入窗口函数

从 2003 年起,SQL 标准中引入了窗口函数,带来了序的概念。有序计算变得容易了许多。上面的三个例子写起来就简单多了。

问题 1,比上期。为了看清楚,把窗口函数拆成多行缩进,方便理解:

SELECT day, price /

LAG(price,1)

OVER (

ORDER BY day ASC

) rate

FROM tbl

LAG 函数实现引用前面的记录。函数里的参数表示找前面第 1 条的 price,OVER 是窗口函数 LAG 的子句(每个窗口函数都有 OVER 子句),它的作用是定义待分析的有序集合,这个例子很简单,待分析集合按照日期有序。

问题 2,移动平均。可以用取前边函数 LAG+ 取后面函数 LEAD 实现,但这里用 AVG 函数更可取,它能支持一个范围内(比如前后十条)的平均,LAG/LEAD 每次只能取到一个值:

SELECT price,

AVG(price) OVER (

ORDER BY day ASC

RANGE BETWEEN 1 PRECEDING AND 1 FOLLOWING

) movingAvg

FROM tbl;

这样取前后 n 条也容易了,只要改变 RANGE BETWEEN 里的范围。

问题 3,分组内的有序计算。每支股票的所有股价是一个分组,窗口函数对它也做了支持:

SELECT code, day, price /

LAG(price,1)

OVER (

PARTITION BY code

ORDER BY day ASC

) rate

FROM tbl

OVER 下的 PARTITION BY 子句描述了怎么划分分组,LAG 操作会限定在每个组内。这比之前的 JOIN 做法好了很多,描述分组很直观。;而 JOIN 做法是对数据做组合排序,虽然实际上也是分组的效果,但不容易理解到位。

2. SPL的解决方案

问题前面解读过了,先看下问题 1 的 SPL 脚本:

db1db3f0bc310069ffda5a071541ddcd.png

A1: 从数据文件导入股市数据表

A2: 使用函数 sort 按日期排序后,计算每天股价与前日的涨幅。其中 price[-1] 表示前日的价格。函数 derive 用于为序表增加计算列。

SPL 同样也支持从数据库中读取数据表,比如 A1 可以改为:

3def30f8129e01a730eab2afe19b5e4f.png

A1 的计算结果是一个序表,SPL中的序表是有序集合,集合的成员是有次序的,这一点与Java等高级语言中的数组类似。可以通过序号来访问成员,是有序集合的基本功能。所以在处理有序运算问题时,有序集合具有天然的优势。访问前一个交易日的数据,对于 SQL 来说比较复杂,需要子查询或者窗口函数的帮助。但是对于有序集合来说,只要访问当前序号 -1 的成员就可以了。不但运算效率更高,理解起来也更加简单。

我们继续看一下问题 2 和问题 3 的解决方案。问题 2:

2a5f255bb65b104931bcf1d4e96d8b3f.png

导入股市数据表,并按日期排序。计算当日、前一日和后一日的股价平均值。其中 price[-1:1] 表示从前一日到后一日的股价。

问题 3:

2edee239b4d3dd35d65504c6e3169dc2.png

导入股市数据表,并按日期排序。使用函数 group 根据股票代码分组。每支股票分别计算当日与前一日股价的涨幅。其中符号 ~ 用来表示当前成员。

使用 SPL 来解决问题 2 和问题 3 时,仍然是通过相对的位置序号来访问相邻成员。解题思路与问题 1 类似,问题 2 只是从访问前 1 天变成访问连续 3 天,问题 3 引入了多支股票所以先按股票代码进行了分组。

二.序号定位

1. SQL的解决方案

有序集合里找相邻记录,属于相对位置定位,有时我们还会找绝对位置的记录,比如计算每天股价与第一天上市价的涨跌差距:

SELECT day, price-FIRST_VALUE(price) OVER (ORDER BY day ASC) FROM tbl

或者,已经知道第 10 天是最高股价,计算出每天和它的差距:

SELECT day, price-NTH_VALUE(price,10)OVER (ORDER BY day ASC) FROM tbl

再看复杂点的情况,要定位的序号事先未知,需要根据数据计算出来:

4、 股票按照股价排序,取出中间位置的股价(中位数)

先看简单的单支股票的解法,按照股价排序后,中间位置还不知道在哪,这时得根据实际股票数据的数量算出中间位置:

SELECT *

FROM

SELECT day, price, ROW_NUMBER()OVER (ORDER BY day ASC) seq FROM tbl

WHERE seq=(

SELECT TRUNC((COUNT(*)+1)/2) middleSeq FROM tbl)

FROM 里的子查询用 ROW_NUMBER() 给每行生成序号,WHERE 里的子查询计算出中间序号。这个 SQL 里有两个注意事项,一是不能直接针对第一个子查询内部过滤,因为 WHERE 里不能使用同级 SELECT 中的计算字段,这是 SQL 执行顺序导致的;二是 WHERE 里的子查询结果一定是一行一列的单个值,这时能直接把它看成单个值和 seq 做等值比较。

计算多支股票中位数的 SQL 如下:

SELECT *

FROM

(SELECT code, day, price,

ROW_NUMBER() OVER (PARTITION BY code ORDER BY day ASC)

FROM tbl) t1

WHERE seq=(

SELECT TRUNC((COUNT(*)+1)/2) middleSeq

FROM tbl t2

WHERE t1.code=t2.code

)

除了增加窗口函数里的PARTITION BY,还要注意计算中间位置时,查询条件也要限定在一支股票内。

5、 每支股票最高价格日与前一天相比涨幅是多少

这个问题需要两种排序方式组合起来定位,还是先看单支股票:

SELECT day, price, seq, rate

FROM (

SELECT day, price, seq,

price/LAG(price,1) OVER (ORDER BY day ASC) rate

FROM (

SELECT day, price,

ROW_NUMBER ()OVER (ORDER BY price DESC) seq

FROM tbl

)

)

WHERE seq=1

连续两层子查询都通过窗口函数给原始数据增加有用信息,ROW_NUMBER 把价格从高到低标上序号,通过 LAG 计算出每天的涨幅,最后过滤出价格最高的一天就可以了(seq=1)。

注意过滤出最高价格不能先于涨幅的计算,最高价格的前一天还不知道在哪里,先过滤掉,后面就算不出来涨幅了。

前面已经有几个针对分组做有序计算的例子了,这个题就不给出最终答案了,读者有兴趣可以自己尝试写写怎么得出多支股票最高价时的涨幅。

2. SPL的解决方案

问题 4 要取出股价的中位数SPL 脚本如下:

a0fd32d7daf7e6acf861f8783e48d0b6.png

导入股市数据表,并按股价排序。根据股票代码分组后,每支股票分别取出股价中位数。

解题思路是,股票代码相同的股票分为一组并按股价排序,接下来每支股票的分组子集按照中间位置的序号访问成员就可以了。

我们再来看一下问题 5,每支股票最高价格日与前一天相比涨幅是多少。SPL 脚本如下:

3ee4f63074a293fc4c8b41f8b260f713.png

导入股市数据表,并按日期排序。根据股票代码分组。使用函数 pmax 定位股价最大值所在位置,再使用函数 calc 在指定位置上进行计算。

SPL 处理定位问题通常来说分为两步:首先获取成员或者满足条件的位置(序号),然后我们就可以根据序号进行访问或计算了。我们并不需要自己来实现定位,SPL 提供了很多定位函数,用于查找成员或表达式在序表中的位置。

三.有序分组

1. SQL的解决方案

有序信息还可以用于分组。看这个例子:

6、 一支股票最多连续上涨过几天。

这个问题有点难想了。基本的思路是把按日期有序的股票记录分成若干组,连续上涨的记录分成同一组,也就是说,某天的股价比上一天是上涨的,则和上一天记录分到同一组,如果下跌了,则开始一个新组。最后看所有分组中最大的成员数量,也就是最多连续上涨的天数。

这种分组比较特殊,和记录的次序有关,而 SQL 里只支持等值分组,就需要把这种有序分组转换成常规的等值分组来实现。过程是这样:

1) 按日期排序,用窗口函数取出每天的前一天股价;

2)对比,如果上涨了的标记为 0,下跌的标记为 1;

3)累加当前行以前的标记,累加的结果类似 0,0,1,1,1,1,2,2,3,3,3…,这些就是我们需要的组号了;

4)现在可以用 SQL 常规的等值分组了。

完整的 SQL 写出来是这样:

SELECT MAX(ContinuousDays)

FROM (

SELECT COUNT(*) ContinuousDays

FROM (

SELECT SUM(RisingFlag) OVER (ORDER BY day) NoRisingDays

FROM (

SELECT day, CASE WHEN price>

LAG(price) OVER (ORDER BY day) THEN 0 ELSE 1 END RisingFlag FROM tbl

)

) GROUP BY NoRisingDays

)

这个题已经不简单了,嵌套了四层的子查询。细追究下解题思路,就得说 SQL 语言与 JAVA/C 语言的不同特点,SQL 是集合化语言,提供的计算直接针对集合,没有显式可精细控制的循环操作,更没有过程中的临时变量可利用,这导致解决问题的思路和人的自然思路差异比较大,得变换思路,通过几个规整的集合计算实现出等价效果;用非集合化的语言 JAVA 或 C,比较贴合自然思路,循环处理每个数据,过程中产生新组或加入旧组很直观。当然 JAVA 等语言基本上没有提供集合运算,也是各有特长。

合理的查询需求在复杂程度上不会止步:

7、 连续上涨超过三天的股票有哪些?

这个问题题是有序分组 + 分组子集,最后再加个常规的分组、聚合值过滤(HAVING)。通过上个查询的思路得到每支股票的所有上涨组,最外面套上分组运算得出每支股票的最大上涨天数,并用聚合后的条件运算 HAVING 过滤出上涨大于三天的:

SELECT code, MAX(ContinuousDays)

FROM (

SELECT code, NoRisingDays, COUNT(*) ContinuousDays

FROM (

SELECT code,

SUM(RisingFlag) OVER (PARTITION BY code ORDER BY day) NoRisingDays

FROM (

SELECT code, day,

CASE WHEN price>

LAG(price) OVER (PARTITION BY code ORDER BY day)

THEN 0 ELSE 1 END RisingFlag

FROM tbl

)

) GROUP BY NoRisingDays

)

GROUP BY code

HAVING MAX(ContinuousDays)>=3

这个 SQL 已经很难看懂了。

2. SPL的解决方案

我们先看一下问题 6,一支股票最多连续上涨过几天。SPL 脚本如下:

2136ca12e058b3771bb0f5bbc54db6d4.png

导入股市数据表,并按日期排序。使用函数 group 的选项 @o,根据股价是否上涨进行分组。分组时只和相邻的对比,当股价是否上涨发生变化时产生新组。最后统计连续上涨的天数。

解题思路是,统计出股票每一次连续上涨的天数,再从中选出最长的一组。SPL 不仅语法简单,更重要的是逻辑清晰,只要按思路顺序编写就可以了。SQL 和 SPL 处理有序分组问题的差别如此巨大,本质上因为 SQL 以无序集合为基础,而 SPL 的序表是有序集合,更擅长于有序计算。除此以外,SPL 还提供了大量的函数,从而更加降低了使用难度。

问题 7,连续上涨超过三天的股票有哪些。SPL脚本如下:

43a30e397a7c1f172d39625289b90f67.png

导入股市数据表,并按日期排序。先按照股票代码分组,再按照问题 6 的方法,计算出每支股票连续上涨的最大天数,最后选出连续上涨超过 3 天的。

这个问题的 SQL 解决方案已经很难看懂了,但是 SPL 脚本还是很简单的。与问题 6 相比,仅仅是多了一个按股票代码分组的过程。SPL 的分组与 SQL 的分组有着本质上的区别。SQL 的分组除了只能得到分组汇总的结果,查询时也只能选出分组时使用的字段和聚合结果。而 SPL 使用直观的记录分组,比如本例中,将相同股票代码值的记录分在一组,分组子集中保留了数据的全部信息。正因为如此,我们才可以对这些分组子集进行下一步的计算。例如在本例中,我们可以对着每个分组子集再次进行有序分组。

总结

从上面的讨论可以看出。没有窗口函数 SQL 对有序运算极端不适应(目前还有些数据库不支持窗口函数),理论上可以写,但实际的麻烦程度基本上等同于不能用。在引入窗口函数后,有序计算得到了很好的改善,不过对于稍复杂情况还是相当麻烦。

这个原因在于 SQL 的理论基础,也就是关系代数,是以无序集合作为基础的,仅靠窗口函数这种打补丁的办法并不能从根本上解决问题。

其实,计算机语言中的数组(即集合)是天然有序的(有序号),在 Java/C++ 这些高级语言的思路下很容易理解和实现有序计算,但是这类语言的集合计算能力又比较弱,实现上面这些问题的代码也不短(虽然有序计算的解题思路难度并不大)。

esProc 的 SPL 可以很好地解决这一问题。esProc 是专业的数据计算引擎,基于有序集合设计,同时提供了完善的集合运算,相当于 Java 和 SQL 优势的结合。在 SPL 的支持下,有序集合计算会非常容易。

SPL 中提供了跨行引用的语法,也支持有序分组等运算,有了这些后,上面那些问题只要按自然思维去组织计算逻辑,一行代码就能优雅地写出来。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/489800.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前方高能!AI 大牛 LeCun 设想下一个新前沿:摈弃深度学习的所有概率技巧,改而掌握不断转变的能量值...

来源:云头条据深度学习界的领军人物Yann LeCun声称,AI的下一个发展阶段可能是摈弃深度学习的所有概率技巧,改而掌握不断转变的能量值。据说工程师(以及一些科学家,但以工程师为主)早在坐到板凳上搞设计之前…

2019年中国智能制造发展现状及趋势分析报告

来源:前瞻产业研究院未来智能实验室是人工智能学家与科学院相关机构联合成立的人工智能,互联网和脑科学交叉研究机构。未来智能实验室的主要工作包括:建立AI智能系统智商评测体系,开展世界人工智能智商评测;开展互联网…

元学习—Meta Learning的兴起

来源:专知【导读】元学习描述了训练深度神经网络相关的更高级别的元素。在深度学习文献中,“元学习”一词经常表示神经网络架构的自动化设计,经常引用“ AutoML”,“少量学习”或“神经架构搜索”。OpenAI的魔方机器人手的成功源于…

python3 rid1.7.4.2 控制台中文乱码_TL;DR - 有关 Python 2 和 Sublime Text 中文 Unicode 编码问题的分析与理解...

TL;DR 问题背景: 相信很多用 Sublime Text 来写 Python 2 的同学都遇到过以下这个问题(例如这位同学 /t/100435 和这位同学/t/163012 ): 在 Sublime Text 里用 Cmd (Ctrl) B 运行代码 print u中文,想要打印出 unicode…

服务器行业深度解析:服务器未来需求知多少

来源:国盛证券一、 全球公有云加速渗透叠加企业上云大趋势来临1. 全球云领军收入增速维持高位,Q2 CAPEX 出现恢复信号全球云计算进入甜蜜点,IaaS 市场主导增长。1)2017 年 6 月,Morgan Stanley 认为全球云计算行业进入…

海上瓶子下有东西吗_洗衣液瓶子我从来不扔,瓶身这样剪几刀,解决了很多家庭的大烦恼...

洗衣液瓶子相信家家户户都会有,每次用完的空洗衣液瓶你都扔掉了吗?那就太可惜了,卖废品也卖不了几毛钱,我们可以将废弃的洗衣液瓶简单剪几刀,就能够变废为宝了,能够解决很多家庭生活中的大烦恼。今天就教大…

光耦继电器

光耦继电器(光电继电器) AQW282SX 282SZ 280SX 280SZ 284SX 284SZ 212S 212SX 21 2SZ 文章目录 光耦继电器(光电继电器)前言一、光耦继电器是什么二、光耦继电器的类型三、光电耦合器的应用总结前言 光耦继电器在工业控制、通讯、医疗设备、家电及汽车电子等领域得到广泛应…

媒体查询响应式布局的几个尺寸_媒体查询实现响应式布局

本文主要介绍 media 查询的使用。通过媒体查询,在不同的屏幕尺寸下,可以设置不同的样式。以此,可以完美解决不同屏幕适配的问题。话不多说,先来看看效果:CSSmedia screen and (max-width: 400px) {.btn {background-co…

为什么说,我们可能是宇宙中唯一的智慧生命?

来源:原理我们在宇宙中是孤独的吗?这个问题可归结为:智慧究竟是自然选择的一种可能结果,还是一种不太可能的侥幸?显而易见的是,可能的事件可以经常发生;不太可能的事件很少发生,或者…

jeecg输入中文查询导表为空_学术利器—SCI期刊影响因子查询/中文核心期刊查询系统更新...

吐槽想起自己第一次投中文期刊的情形:当时学校最低要求是发表一篇核心级别的期刊论文,但是哪些期刊是核心期刊呢?完全不知道!都怎么投稿呢?也完全不知道!只能问问周围的同学或者师兄师姐。他们也就知道谁谁…

Python 学习随笔1

在一个列表中,找出重复数组的位置。 比如在列表name [1, 5, 8, 22, 56, 2, 8, 45, 7, 2, 35, 2, 486, 2, 152, 111, 265, 2, 2]中,找出2的位置。 方法1: 流程为: 找到第一个2的位置,然后在2之后的一个数后面切片&…

震撼!15项世界互联网领先科技成果发布,将对你的生活产生什么影响?

来源:浙江发布10月20日下午,世界互联网领先科技成果发布活动在乌镇互联网国际会展中心举行。今年6月,世界互联网大会组委会向全球互联网企业、科研机构、高等院校以及个人征集全球互联网领域的领先科技成果,收到了来自中国、美国、…

java执行查询postgresql得到中文乱码_Greenplum: 基于PostgreSQL的分布式数据库内核揭秘(上篇)...

关于作者姚延栋,山东大学本科,中科院软件所研究生。PostgreSQL中文社区委员,致力于Greenplum/PostgreSQL开源数据库产品、社区和生态的发展。一、数据库内核揭秘Greenplum 是最成熟的开源分布式分析型数据库(今年6月份预计发布的 Greenplum 6…

关于授予81项成果2019年度“吴文俊人工智能科学技术奖”的决定

来源:人工智能人物为加快实施国家创新驱动发展战略,深入贯彻《新一代人工智能发展规划》,更好地推进科教兴国、人才强国的政策落实,弘扬“尊重劳动、尊重知识、尊重人才、尊重创造”的良好风尚,通过推选优秀的智能科学…

mysql索引 和 es索引_MySQL索引 VS ElasticSearch索引

今天MySQL数据库栏目介绍MySQL索引与ElasticSearch索引的对比。前言这段时间在维护产品的搜索功能,每次在管理台看到 elasticsearch 这么高效的查询效率我都很好奇他是如何做到的。这甚至比在我本地使用 MySQL 通过主键的查询速度还快。为此我搜索了相关资料&#x…

开启httponly之后登陆失败_二次元约会模拟《少女都市》正式版登陆Steam 橘势大好...

《少女都市(Shoujo City)》于2018年1月在Steam开启了抢先测试,昨天发布了1.0正式版。这是一款专注于二次元和御宅文化的百合向约会模拟游戏,目前Steam好评率94%,自带简体中文。《少女城市》结合了美少女视觉小说与沙盒式的城市探索冒险&#…

科技/IT:2019 年 Q3 表现最佳和最差的企业

来源:云头条在2019年上半年经历稳步上涨之后,由于全球经济的不确定性和美中贸易紧张局势,2019年第三季度的股市如同过山车。道琼斯指数第三季度(截至9月30日)以26916.83点收盘,比2019年6月28日收盘价上涨1.…

java图片压缩不失真_软件分享 | Lit图片压缩

软件分享01软件名称Lit图片压缩02软件版本V1.2.0.01603软件简介Lit图片压缩app是一款免费简单好用的图片压缩工具,让图片在不失真的情况下,进行压缩和裁剪,轻松就能压缩成你想要的尺寸,并且原来的像素不失真,保持原画质…

从大型主机到个人计算机:机器人产业可以从pc普及革命中学到什么?

来源:大数据文摘出品自主化机器人已逐渐变得无处不在。自动吸尘器、自动割草机、会简单交互的小玩具,以及呼之欲出的自动驾驶汽车,都可以看作是一个能实现某种自动功能的机器人。一辈接着一辈,我们一直在期待出现《星球大战》中的…

【Poj1017】Packets

http://poj.org/problem?id1017 艰难啊 弄了很久咧 拍了几十万组,以后拍要多组数据 Solution 从大wangxiaofang 从大往小放,有空余的从大往小填 注意细节 Notice b<0的情况,还有就是当前填充完了,还剩一点给下一个(小一点的)填 Code // This file is made by YJinpeng&…