在开发中涉及数采部分,部分PLC的元软件地址是用16进制标识的。
例如三菱的 M1F 这样,同步时上位机端保存最好也同样记录一样名字的地址,这里就需要16进制的加减运算。
最简单的计算方式是:

(Convert.ToInt32(saddr, 16) + inc).ToString("x").ToUpper();

拓展开来,要是需要进行一个任意长度的16进制加法呢,找了一下网上也没看到有比较好的操作。
检查梳理一下思路,就是从低位到高位逐位相加,然后有进位的参与后边运算,代码如下

 public string HexAdd(string first, string second) {
    var src = first.ToCharArray();
    var des = second.ToCharArray();
    char[] res;
    if (src.Length < des.Length) {
        res=HexAddByChars(des.Reverse().ToArray(), src.Reverse().ToArray());
    } else {
        res=HexAddByChars(src.Reverse().ToArray(), des.Reverse().ToArray());
    }
    return res != null ? string.Concat(res.Reverse()) : string.Empty ;
}

public string HexAdd(string saddr, int inc) {
    return (Convert.ToInt32(saddr, 16) + inc).ToString("x");
}

private char[] HexAddByChars(char[] a, char[] b) {
    var res = new char[a.Length];
    var padd = 0;
    for (var i =0; i< a.Length; i++) {
        if (i >= b.Length) {
            res[i] = HexAddByChar(a[i], Convert.ToChar(padd.ToString()), out padd);
            padd = 0;
        } else {
            if (padd > 0) { //低位结果有进位运算时
                var sa = HexAdd(a[i].ToString(), padd);
                var re = HexAdd(sa, b[i]);
                if (re.Length > 1) {
                    padd = int.Parse(re.Substring(0, 1));
                    res[i] = Convert.ToChar(re.Substring(1));
                } else {
                    res[i] = Convert.ToChar(re);
                }
            } else {
                res[i] = HexAddByChar(a[i], b[i], out padd);
            }
        }
    }
    return res;
}
private char HexAddByChar(char a, char b, out int padd) {
    padd = 0;
    var tres = b=='\0'?a.ToString(): (Convert.ToInt32(a.ToString(),16) + Convert.ToInt32(b.ToString(),16)).ToString("x");
    if (tres.Length > 1) {
        padd = int.Parse(tres.Substring(0, 1));
    }
    return Convert.ToChar(tres.Length>1?tres.Substring(1):tres);
}

注意:运算需要从低位往高位推进,所以上边操作将16进制字符串分拆成数组后,需要先逆序再操作,操作完再逆序保存回来。

标签: 16进制, 任意长度, 算法

评论已关闭