我正在使用一些旧版软件(RSLogix 500,不要问)对 PLC 进行编程,它本身不支持模数运算,但我需要一个。我无权访问:模数、整数除法、局部变量、截断操作(尽管我可以通过舍入来破解它)。此外,我可以使用的所有变量都排列在按数据类型排序的表格中。最后,它应该适用于浮点小数,例如 12345.678 MOD 10000 = 2345.678
。
如果我们建立方程式:
dividend / divisor = integer quotient, remainder
有两个明显的实现。
实现 1:
执行浮点除法:dividend/divisor = decimal quotient
。然后拼凑一个截断操作,以便找到 整数商
。将它乘以除数
,求出被除数
与除数之间的差值,得到余数
。
我不喜欢这个,因为它涉及到一堆不同类型的变量。我不能将变量“传递”给子程序,所以我只需要分配位于多个不同变量表中的一些全局变量,这很难遵循。不幸的是,“难以理解”很重要,因为它需要足够简单,维护人员才能搞定。
实现 2:
创建一个循环,使得 while dividend > divisor
divisor = dividend - divisor
。这非常干净,但它违反了 PLC 编程的重要规则之一,即永远不要使用循环,因为如果有人无意中修改了索引计数器,您可能会陷入无限循环,并且机器会发疯或出现无法恢复的故障。 Plus 循环很难进行维护和故障排除。另外,我什至没有循环指令,我必须使用标签和跳转。呃。
所以我想知道是否有人有比这两者更聪明的数学技巧或更智能的模数实现。我可以访问 + - */、指数、sqrt、三角函数、对数、绝对值和 AND/OR/NOT/XOR。
最佳答案
您要处理多少比特?你可以这样做:
if dividend > 32 * divisor dividend -= 32 * divisor
if dividend > 16 * divisor dividend -= 16 * divisor
if dividend > 8 * divisor dividend -= 8 * divisor
if dividend > 4 * divisor dividend -= 4 * divisor
if dividend > 2 * divisor dividend -= 2 * divisor
if dividend > 1 * divisor dividend -= 1 * divisor
quotient = dividend
展开次数与红利
中的位数一样多。一定要小心那些溢出的乘数。这就像你的#2,除了它需要 log(n) 而不是 n 次迭代,所以完全展开是可行的。
关于algorithm - 一个聪明的自制模数实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14841280/