本帖最后由 lirui11 于 2019-8-18 17:06 编辑
前言
在MC里进行运算时,有时计分板位数太少容易溢出,或者单纯只是想在MC里算点什么却发现精度不够。针对以上问题,我制作了这套数据包,理论上能够将任意位数的数进行运算。
加载数据包后,请输入
来初始化这个数据包
如何定义一个数
既然计分板的位数不够,我们就想到将每一位数存入数组中来表示一个数字。
在这个数据包里,数字以物品的形式存在,任何一个带有自定义标签num:{}的物品就是一个数,甚至一个普通的物品都可以表示 0 这个数。num标签结构如下:{num:{sign:,a:[],b:[]}}
其中,sign存储这个数的正负号,sign:- 表示这是个负数,sign:+ 表示这是个正数并且你希望这个数在显示的时候将+号一起显示出来。如果没有sign标签,默认为正数。
a:[]存储这个数的整数部分,将每一位从最高位依次写进数组里,如a:[1,2,3]表示整数部分是123。如果没有a标签或者a中没有元素,默认为0。
b:[]存储这个数的小数部分,将每一位从最高位依次写进数组里,如b:[4,5,6]表示小数部分是456。如果没有b标签或者b中没有元素,默认为0。
*所以,num:{a:[1,2,3]}表示数字123,num:{b:[4,5,6]}表示数字0.456
例子:
num:{sign:-,a:[1,2,3],b:[4,5,6]} ---> -123.456
num:{sign:+,a:[1,2,3],b:[4,5,6]} --->+123.456
num:{a:[1,2,3],b:[4,5,6]} --->123.456
num:{sign:-,b:[4,5,6]} --->-0.456
num:{} --->0
- give @s stone{num:{sign:-,a:[1,2,3],b:[4,5,6]}}
复制代码
函数介绍
下列函数中被折叠的函数表示这个函数并不是正常的进行运算,仅进行绝对值的运算,主要用于开发新函数
function num:get
玩家执行后,将会把手持物品表示的数字tellraw输出给自己,若没有手持物品,输出0
function num:get/block
执行后,将会把执行点处容器内第一个物品表示的数字tellraw输出给最近的玩家,输出效果同
function num:get,若执行点处没有容器,或容器内没有物品,输出0
function num:add
执行后,将会把执行点处容器内前两个物品表示的数字相加,并将结果输出到第一个物品,同时删除第二个物品,会正确处理正负号
- function num:add/addition
复制代码 执行后,将会把执行点处容器内前两个物品表示的数字的绝对值相加,并将结果输出到第一个物品,同时删除第二个物品。结果的符号与第一个物品一致
|
function num:minus
执行后,将会用执行点处容器内第一个物品表示的数字减去第二个物品的,并将结果输出到第一个物品,同时删除第二个物品,会正确处理正负号
- function num:minus/subtraction
复制代码 执行后,将会用执行点处容器内绝对值大者减去绝对值小者,符号与第一个物品一致,若第一个物品的绝对值更小,会将第一个物品的符号反转。将结果输出到第一个物品,同时删除第二个物品
|
function num:times
执行后,将会把执行点处容器内前两个物品表示的数字相乘,并将结果输出到第一个物品,同时删除第二个物品,会正确处理正负号
- function num:times/multiplication
复制代码 执行后,将会把执行点处容器内前两个物品表示的数字的绝对值相乘,符号与第一个物品一致
|
function num:divided
- scoreboard players set #division_prec temp <要保留的小数位数>
复制代码
需要设置要保留的小数位数(存储在#division_prec的temp计分板上),这个设置是全局性的,某次设置后不用再次设置(除非需要更改)。接下来的除法运算都会保留指定的几位小数。
默认#division_prec的值为16。这个值
必须大于等于0 可以大于16
如:scoreboard players set #division_prec temp 5 接下来的所有除法运算都会保留5位小数(按照四舍五入)如果哪次需要更高精度了,再重新设置
执行后,将会把执行点处容器内第一个物品作为被除数,第二个物品作为除数进行除法运算,并且保留#division_prec位小数,将结果输出到第一个物品,同时删除第二个物品。会正确处理正负号
*除数不能是0,否则将会陷入死循环,直到maxCommandChainLength
*遇到这种情况后请fill ~ 255 ~ ~ 250 ~ air将临时处理用的容器删掉
*除法的算法不是最高效的,如果愿意,可以将除法转化为乘法,例如除以3换成乘0.33333333,除以2换成乘0.5
- function num:divided/division
复制代码 执行后,将会把执行点处容器内前两个物品表示的数字的绝对值相除,符号与第一个物品一致,其他注意事项与function num:divided一致
|
function num:is_smaller
执行后,将会比较执行点处容器内前两个物品表示数字的大小,并将结果输出到#is_smaller的temp计分板上。会考虑正负号
如果第一个>第二个 输出0
如果第一个<第二个 输出1
如果第一个=第二个 输出2
- function num:is_smaller/abs
复制代码 执行后,将会比较执行点处容器内前两个物品表示数字的绝对值大小,并将结果输出到#is_abs_smaller的temp计分板上,映射关系同上
|
function num:exchange
执行后,将会把执行点处容器内前两个物品表示的数字互换,此举不会把物品的id,数量等互换,只互换num标签
- function num:exchange_not_sign
复制代码 执行后,将会把执行点处容器内前两个物品表示的数字的绝对值互换,此举不会把物品的id,数量等互换,也不会互换符号,只互换num标签下的a:[],b:[]
|
function num:import/score
需要事先给#score的temp计分板赋值,若不赋值则会使用当前#score的分数
执行后,将会把#score的temp分数转化成一位一位的数组,并把结果输出到~ 250 ~ Items[0].tag.push
例如,#score的分数是16380,执行函数后~ 250 ~的容器内第一个物品的tag就会有自定义标签push:[1,6,3,8,0]
然后使用data modify … from block ~ 250 ~ Items[0].tag.push来将数组导出
不要忘记setblock ~ 250 ~ air
注意
如果位数过多,计算所需命令也会很多,请适当调大/gamerule maxCommandChainLength [value]
如果不小心触及到了这个限制,请输入/fill ~ 255 ~ ~ 250 ~ air来删除计算过程临时的容器
所以,最好也不要在y轴250~255的地方使用函数(目前只有255和250会有临时容器出现,中间的位置先预留出来)
我能用这个数据包做什么
进行高精度运算,实现原先看起来不可能的事情 在MC里算XXX!
如果是用于命令层面,实用性到不是很大,因为将大数反过来输出到nbt上不是很容易,即使已经表示出123.456789456789456,把它输出为浮点数并不容易,几乎也是不可能的,这样看来又似乎没什么用了。不过一个东西刚出来的时候,谁知道会有什么用呢?
下载地址
big_num.zip
(20.22 KB, 下载次数: 9)
big_num_extra.zip
(1.68 KB, 下载次数: 6)
备用网盘地址
https://pan.baidu.com/s/16xu4-HzWbKzTGtMGRmDlVQ 提取码miwv
big_num即为本基础模块,包括了上文介绍的所有函数
big_num_extra是我以本模块为基础做的一个简单的阶乘函数,先给#fact的temp计分板赋值,然后输入/function num_extra:fact即可计算#fact的阶乘,会在当前位置放置一个箱子输出结果,输入/function num:get/block查看
*可能会考虑做出其他数学函数,也可能会咕
感谢
@xiaodou123
应该是叫这个名字吧,(反正群里名片是这个,@错了别找我),反正“小豆”就是了 |
他带头讨论了这个问题,我才得以动力制作这个数据包,感谢!
计算1000!
共有2568位
402387260077093773543702433923003985719374864210714632543799910429938512398629020592044208486969404800479988610197196058631666872994808558901323829669944590997424504087073759918823627727188732519779505950995276120874975462497043601418278094646496291056393887437886487337119181045825783647849977012476632889835955735432513185323958463075557409114262417474349347553428646576611667797396668820291207379143853719588249808126867838374559731746136085379534524221586593201928090878297308431392844403281231558611036976801357304216168747609675871348312025478589320767169132448426236131412508780208000261683151027341827977704784635868170164365024153691398281264810213092761244896359928705114964975419909342221566832572080821333186116811553615836546984046708975602900950537616475847728421889679646244945160765353408198901385442487984959953319101723355556602139450399736280750137837615307127761926849034352625200015888535147331611702103968175921510907788019393178114194545257223865541461062892187960223838971476088506276862967146674697562911234082439208160153780889893964518263243671616762179168909779911903754031274622289988005195444414282012187361745992642956581746628302955570299024324153181617210465832036786906117260158783520751516284225540265170483304226143974286933061690897968482590125458327168226458066526769958652682272807075781391858178889652208164348344825993266043367660176999612831860788386150279465955131156552036093988180612138558600301435694527224206344631797460594682573103790084024432438465657245014402821885252470935190620929023136493273497565513958720559654228749774011413346962715422845862377387538230483865688976461927383814900140767310446640259899490222221765904339901886018566526485061799702356193897017860040811889729918311021171229845901641921068884387121855646124960798722908519296819372388642614839657382291123125024186649353143970137428531926649875337218940694281434118520158014123344828015051399694290153483077644569099073152433278288269864602789864321139083506217095002597389863554277196742822248757586765752344220207573630569498825087968928162753848863396909959826280956121450994871701244516461260379029309120889086942028510640182154399457156805941872748998094254742173582401063677404595741785160829230135358081840096996372524230560855903700624271243416909004153690105933983835777939410970027753472000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 |
由于计算时间有点久,所以这段gif是拼凑前后结果出来的,实际上计算没那么快
或许这段日志能说明问题
- [15:37:00] [main/INFO]: [CHAT] 已将#fact的[temp]分数设为1000
- [15:51:39] [Server thread/INFO]: [16380: 已执行函数num_extra:fact中的51032131条命令]
- [15:51:39] [Server thread/WARN]: Can't keep up! Is the server overloaded? Running 875190ms or 17503 ticks behind
复制代码