前言
为了更好的记录数据和查找数据,在进行具体数字运算前,需按照一定的规则确定一致的位数,然后舍去某些数字后面多余的尾数。现在被广泛使用的数字修约规则主要有四舍五入规则和四舍六入五留双规则。
我们对于四舍五入修约规则再熟悉不过了,这个规则贯彻了小学中学,甚至大学的数字修约过程。利用这种方法修约简单快捷,但实际上这种规则由于舍去的是“1、2、3、4”,入位的是“5、6、7、8、9”,这样必然会造成结果的系统偏高,误差偏大1/9。
与此相比,四舍六入五留双规则就精确的多得多,但与此同时也会相对麻烦一些。
四舍六入五留双规则的具体使用方法是:
(1)当尾数小于或等于4时,直接将尾数舍去;
(2)当尾数大于或等于6时,将尾数舍去并向前一位进位;
(3)当尾数为 5,而尾数后面的字均为 0时,应看尾数5的前一位:若前一位数字此时为奇数,就应向前进一位;若前一位数字此时为偶数,则应该将尾数舍去。
(4)当尾数为5,而尾数后面的数字不为0时,无论前一位在此时为奇数还是偶数,也无论5后面不为0的数字在哪一位上,一律向前一位进位。
在水文测验学上,取用位数和有效数字位数时常不一样,比如断面面积取三位有效数字,但小数不超过两位。针对这种需求,下文中提供的代码进行了实现。
算法实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | /// <summary> /// 数字修约 /// </summary> /// <param name="num">带修约数字</param> /// <param name="valnum">有效数字</param> /// <param name="dotsuffix">小数点后数字数</param> /// <returns>修约后的数字</returns> public static double Trim(double num, int valnum=2, int dotsuffix=2) { double mul = 0, Tnum = 0; for (int i = 0; ; i++) { mul = Math.Pow(10, i); Tnum = num / mul; if (Tnum <= 10) { if (Tnum < 1) { if (valnum == dotsuffix) valnum++; else valnum = dotsuffix; } break; } } List<char> tchar = Tnum.ToString("F10").ToList(); long ctr = int.Parse(Tnum.ToString("F10").Substring(valnum + 2)); int prekey = int.Parse(tchar[valnum].ToString()); int key = int.Parse(tchar[valnum + 1].ToString()); if (key > 5 || (key == 5 && (ctr > 0 || (ctr == 0 && prekey % 2 != 0)))) prekey++; tchar[valnum] = prekey.ToString()[0]; tchar.RemoveRange(valnum + 1, tchar.Count - valnum - 1); Tnum = double.Parse(new string(tchar.ToArray())) * mul; return Tnum; } |