作者 | 主题 |
---|---|
伊默 至圣 经验值:18578 发帖数:4264 精华帖:118 |
楼主 2019-12-10 19:31:20
主题:BUG? BUG? 我觉得应该算是BUG 现场一台机器出现了个问题,我是按照FOR-NEXT循环写的程序, 总共有15节烘箱加热,可是现场反映就第13节动作异常! 我是打死不信啊! 原因无它,用循环语句循环15遍,要出问题就都有问题啊,怎么可能单单第13节有问题呢? 今天到现场监控了一下,别说,还真是第13节有问题! 问题出在那儿呢? 程序中有如下一句:(为了求当前字总共16位当中那个位为1的最高值,比如第10位为1,则返回10) iNum := DINT_TO_INT(TRUNC(LN(UINT_TO_REAL(SWAP(#iTemp)))/LN(Real#2.0))); 就这么简单的一句,可是当iTemp=32时,得到的结果iNum却还是12! 按照计算应该是13才对呀! 10#32= 16#20 , Swap后即为16#2000=10#8192 LN(8192)=9.010913... LN(2.0)=0.693147... 两者相除,结果等于13.000028854,截尾取整,按理说应该是13吧? 可是PLC运算的结果就是12 ! 其他的条件,比如iTemp=16则iNum=12, iTemp=64则iNum=14都是正常的! 我没招了! 只能人为地改啊! 把语句改成: iNum := DINT_TO_INT(TRUNC(LN(UINT_TO_REAL(SWAP(#iTemp)))/LN(Real#2.0) + 1.0E-6)); 人为地加个极小的数,则正常工作了! 后来再玩一把,改成: iNum := DINT_TO_INT(TRUNC(LN(UINT_TO_LREAL(SWAP(#iTemp)))/LN(LReal#2.0))); 各位看官,注意到区别没? 将原程序的REAL改成了LREAL, 则也正常工作了! 大家觉得这算BUG吗? 有兴趣的朋友测试一下,就量iTemp=32时才有问题。
I can do it
|
yming 至圣 经验值:127285 发帖数:21992 精华帖:824 |
1楼 2019-12-10 21:26:20
主题:回复:BUG? BUG? 我觉得应该算是BUG 嘿嘿。用到浮点就会有这种问题。更别说变换了。浮点数十进制有效位数是很少的。 当年16位的电脑更出错了。初代8位电脑计算才麻烦呢。 浮点计算不能反复用,越多误差越大、精度越差。 你这种需求应该有专门的函数吧? 我记得这种标准算法不是用左位移;减循环么?
学而时习之,不亦说乎?温故而知新,不亦乐乎?
|
Zane 版主 经验值:76091 发帖数:19115 精华帖:378 |
3楼 2019-12-10 21:55:50
主题:回复:BUG? BUG? 我觉得应该算是BUG 没错,就是这样的,隐式转换的弊端。 另外,浮点转整数有好几个指令呢,只会用TRUNC吗?
Zane
注册自动化系统工程师
Always save before download
|
伊默 至圣 经验值:18578 发帖数:4264 精华帖:118 |
5楼 2019-12-11 08:01:07
主题:回复:BUG? BUG? 我觉得应该算是BUG
ROUND,FLOOR当然都试过,你试试? 再一个我这应用原则上只能用TRUNC,截尾取整,因为我要的是最高位。 另外,这和隐式转换没关系吧? 我都是显示转换,只不过转成REAL有问题,而转成LREAL说没问题罢了。
I can do it
|
master_mb 侠圣 经验值:4030 发帖数:1259 精华帖:6 |
9楼 2019-12-13 08:52:01
主题:回复:BUG? BUG? 我觉得应该算是BUG 9.010913和0.693147是你看到的四舍五入后的结果 说到底还是数据精度问题 最碰巧的可能值分别是:9.01091245和0.6931474 9.0109125/0.6931474=12.99999466203004
QQ 402550360 TEL 17606539722
|
伊默 至圣 经验值:18578 发帖数:4264 精华帖:118 |
11楼 2019-12-13 11:04:13
主题:回复:BUG? BUG? 我觉得应该算是BUG 不是BUG,的确是我的编程不够严谨。 考虑到浮点数的精度问题,即使后来我改成LREAL类型,也只是把问题掩盖了! 改成DINT_TO_INT(TRUNC(LN(UINT_TO_LREAL(SWAP(#iTemp)))/LN(LReal#2.0) +1.0E-9 )); 可能更能满足实际的应用需要。 这个可以涵盖32位双字的应用。 其实我的应用是求一个字或者双字内 某一个位为1的最高位数。 比如某个数为63,它的二进制为11 1111,通过该指令返回值为 5 (按照ZANE的想法使用ROUND则得到6, 我需要的是截尾取整,而不是简单地四舍五入)。 当然,最靠谱的办法就是用移位判断,但是程序啰嗦,16位字需要移16次,32位字需要移32次, 或者用二分位法。 但是都没有我这个指令来得简洁, 只是简洁过头了没有考虑到精度问题。
I can do it
|
Zane 版主 经验值:76091 发帖数:19115 精华帖:378 |
14楼 2019-12-14 08:59:20
主题:回复:BUG? BUG? 我觉得应该算是BUG
数据取进来,取最高位字节,与0或运算,结果为零,则跳过取下一字节,不为零,则左移取第一位移出值为1的位数,根据字节数与移位次数,(n字节+1)*8-n移位,即得最高位1的位数。
一个双字,最多比较3次移位7次。这种算法也适合长型数据。
Zane
注册自动化系统工程师
Always save before download
|
yming 至圣 经验值:127285 发帖数:21992 精华帖:824 |
15楼 2019-12-14 09:56:52
主题:回复:BUG? BUG? 我觉得应该算是BUG 其实浮点运算是最慢的,布尔运算是很快的。而使用M区变量布尔运算是最快的。 看似程序啰嗦,其实处理起来是速度并不慢。这是PLC中布尔运算器的强项。 这种通用函数功能,真应该写成个FC。
学而时习之,不亦说乎?温故而知新,不亦乐乎?
|
yming 至圣 经验值:127285 发帖数:21992 精华帖:824 |
16楼 2019-12-14 11:00:41
主题:回复:BUG? BUG? 我觉得应该算是BUG 我其实是早年在EXCEL中遇到的。处理财务数据(小数点后两位)时,金额较少时,你看不出来,当处理金额很大时,就会出现错误。和会计手工记账对不上了。这才理解浮点的数据格式和有效位数的问题。 后来在工程计算上,也会使用EXCEL来计算;如计算连续轧制压下量、每道的减径量等计算。理论上当然是使用上道次的结果作为本次计算的初值,计算本道次压下量;实际上不行的!虽然显示的永远是一长串数字,但是有效位数越来越少,计算结果离真值的误差会越来越大。 这主要表现在浮点数据的乘除运算上,改变数据处理方式,浮点乘除运算只用一次,保持可信有效数据长度不至于减少太多。 我记得,早年有个报道,好像是伦敦金融中心的程序员。就是利用这个浮点计算的问题,将银行每天成千上万笔交换中,汇率计算的舍去误差,在程序中偷偷存到自己户头上,居然累计了大量财富。
学而时习之,不亦说乎?温故而知新,不亦乐乎?
|
'Razor 至圣 经验值:20114 发帖数:2773 精华帖:23 |
20楼 2019-12-15 18:08:03
主题:回复:BUG? BUG? 我觉得应该算是BUG 浮点数的运算有好大的坑,如: a+b+c != a+(b+c); a*b*c != a*(b*c);
Less is more……
|
我家牛 奇侠 经验值:9086 发帖数:2334 精华帖:30 |
21楼 2019-12-16 10:16:25
主题:回复:BUG? BUG? 我觉得应该算是BUG 你这是有的数吧? 1.0+1.0+1.0 != 1.0+(1.0+1.0)???; 1.0*0.1*10.0 != 1.0*(0.1*10.0)???; 不过记得哪位大侠说过,浮点数忌讳用等于,应该用区间。
学习ing!学习!
|