找回密码
 点一下
查看: 383|回复: 0

关于求余(取模)时发现的魔兽实数的问题

[复制链接]
发表于 2022-7-18 16:12:00 | 显示全部楼层 |阅读模式
本帖最后由 浮夸的下划线 于 2022-7-18 16:14 编辑

开篇:最近我在制作一个多面板,然后要在多面板的标题上,显示游戏逝去的时间,所以我用了计时器0.1秒循环的自增一个全局变量"js"然后再用百度到的(同时也参考了BJ的取模函数的内容)的求余(取模)公式:
整数商c = [a/b]  ,  计算模或者余数r = a - c*b.(注意c是整数商,我当时就没有注意,就一直怀疑这个公式应该一直得出0的结果才对)

所以我写了这么一个函数(目前我这边依然无法上传图片,显示的都是一个灰色的拼图,无法点击,所以无法上传图片,见谅)
//计时-游戏(js_game_cf,周期0.1秒)action

function js_game_event_act takes nothing returns nothing
        set js_game_ss = js_game_ss + 0.1
        if action_qys(0,0,js_game_ss,1,false) == 0 then
            call dmb_game_sj()
        endif
    endfunction




//求余数(返回实数)-i mod i2(true)  或  r mod r2(false)、采用类型(true or false)
    function action_qys takes integer i,integer i2,real r,real r2,boolean b returns real
        if b == true then
            set i = i - (i / i2) * i2
            set r = I2R(i)
        else
            set r = r - I2R(R2I(r / r2)) * r2
        endif
        return r
    endfunction


参照了BJ函数里面的实数取模,可以说我是复制了他的公式(即else里的set),注意,第二个实数参数是固值1,
然后我打算在计时器0.1秒的动作里面,写一个if判定全局变量js的余数为0,即可判定过了一秒,然后再给多面板的标题改一下,以此做到更改秒数
但是,在我经过制作完毕并测试的时候,却发现时间并未改变,然后又通过debugmsg,输出了变量的值和求余的值,发现,这个求余的值 只会在0.1-1直接徘徊,当我理想的计算认为得出的余数应该是0的时候,他却得出的是1,因此,我在7.17和7.18弄了大概两天,后来又大佬告诉我,是因为实数有误差,后来经过我的测试,解决了这个问题

正片:
由上可知,我们这次讨论的数据仅为,action_qys函数丽的else动作,js变量,以及第二个实数参数固值1
那么由公式,我们可以知道,按照公式,应该是这么一个计算过程

假设js=14,
那么set r = 14 - I2R(R2I(14/1))*1
结果r = 0才对,但是,他输出的就是1,我很奇怪(无法上传截图,见谅)

但由于大佬告知,实数有误后,我尝试了把实数转成10个小数字符串(实际值出现了9个小数),用的函数是 R2SW(即,格式转换实数为字符串)
发现我之前输出的js为14.000的时候,此时通过该函数(R2SW)输出的的值并非14.000000000,而是13.999958976
而后,我开始去验算计算公式,假设我们实际的数值就是13.999...(略去了一些小数,方便书写)
那么此时这个公式set r = r - I2R(R2I(r / r2)) * r2
其计算过程应该为
r = 13.999 - I2R(R2I(13.999/1))*1
r = 13.999 - I2R(R2I(13.999))*1
由于我们知道,魔兽的实数转整数是向下取整的,不管小数是多少(如7.899999,转整数为7;6.21333,转为整数为6)
所以接下来应该是
r = 13.999 - I2R(R2I(13))*1
到了这里,我们就可以惊奇的发现
r = 13.999 - 13
r = 0.999
r = 1
正好印证了之前的测试结果,理想结果输出应该为0时,竟输出为1
由大佬说的,直接的问题确实是实数有误差导致,但是本质的问题还是魔兽本身实数这个东西有问题导致的,在这里要感谢那位大佬的帮助

解决方案:
在我发现这个情况之后,我就想到了实数转为字符串后,再转为实数,结果当实数是整数的时候,后面的小数就为一排0了,14.000000000
这样,通过这个步骤转换来的实数,就可以相对准确的获取到正确的余数了
但是,其他有小数的数值,还会可能出现0.000000300,左右的误差,
也许更准确的是用实数转换为字符串后再截取字符串的2位小数(根据你的需求来设定),再转为实数

作者留言:
其实我前一段时间也有研究过一点点的这个魔兽实数问题,当时确实是发现了,设置的数几个0后面的小数会出现大于0的数值,(即误差),不过当时我并没有怎么用到取模这个东西
这次用到了取模,但之前的东西早就不是记得很清楚了,就没有想到
那么可以说,BJ的函数ModuloReal(即,数学(实数) - 模)是存在这个bug的。
整数取模的,我并没有测试过,按照目测的计算公式和结果,应该不会有什么问题,
致此,感谢各位!
您需要登录后才可以回帖 登录 | 点一下

本版积分规则

Archiver|移动端|小黑屋|地精研究院

GMT+8, 2024-12-21 23:46 , Processed in 0.056284 second(s), 18 queries .

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

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