在实际的生产制造统计中,会有精度丢失的情况. 倘若按照 我们平常所用的 四舍五入,(1234舍掉, 56789 进位)
这样会使整体数据偏大(理论模型).
为了使整体数据保持平均,生产制造有这样一种计算方式,也就是 四舍六入无成双.
例如保留3位有效数字:
1.235 => 1.235
1.2354=>1.235 (0.0004舍掉)
1.2355=>1.236 (0.0005前面是奇数,进位)
1.2365=>1.236 (0.0005前面是偶数,舍弃)
C# 代码如下
/// <summary> /// 格式化 Decimal 数字 用于有效计算 /// </summary> /// <param name="ori"></param> /// <returns></returns> /// <remarks></remarks> public static decimal FormatDecimal(decimal ori) { if (ori == 0) { return 0; } decimal num = ori; decimal result = 0m; int zoome = 1; //小于100的数, 数字放大 10的 指数倍,直到 数字 大于等于100 while (num < 100) { num = num * 10; zoome = zoome * 10; } int int1 = Math.Floor(num); decimal d1 = Math.Floor(num) + 0.5; // 四舍六入 // 5 看尾数 和奇偶 if (num > d1) { //如果 5后面有尾数, 进位 result = int1 + 1; } else if (num == d1) { // 看前一位 偶数不变,奇数 +1 if (int1 % 2 == 0) { result = int1; } else { result = int1 + 1; } } else { //整数 result = int1; } //有效数字取到以后 缩小到原来的数量级 result = result / zoome; return result; } /// <summary> /// 格式化字符串显示 Decimal 数字 /// </summary> /// <param name="ori"></param> /// <returns></returns> /// <remarks></remarks> public static string ShowDecimal(decimal ori) { if (ori == 0) { return "0"; } //首先 得到 格式化之后的数据, 有效数字 ori = FormatDecimal(ori); string strNum = ""; decimal num = ori; //判断是不是 3位及3位以上数字 直接取整数部分 if (num >= 100) { strNum = num.ToString(); } else if (num > 0) { // 三位数以下, 涉及到 取小数点 string s = num.ToString(); // 没有小数点, 先补齐 小数点位数 if (s.Contains(".")) { s = s + "00"; } else { s = s + ".00"; } // 遍历取 3位有效数字 char[] array = s.ToCharArray(); int start = 0; for (int i = 0; i <= array.Length - 1; i++) { if (start == 3) { break; // TODO: might not be correct. Was : Exit For } if (array[i] == ".") { strNum = strNum + "."; } else { int t = int.Parse(array[i]); if (t > 0) { start = start + 1; strNum = strNum + t; } else if (t == 0) { if (start > 0) { start = start + 1; strNum = strNum + t; } else { strNum = strNum + t; } } } } } return strNum; }
SQL 代码如下
create function [dbo].[func_formatDecimal](@wgt decimal(16,6)) returns numeric(16,3) as begin if @wgt = 0 begin return 0 end declare @num decimal(16,6),@result numeric(16,3),@zoome integer set @num = @wgt set @result = 0 set @zoome = 1 --小于100的数, 数字放大 10 的倍数 while @num<100 begin set @num = @num * 10 set @zoome = @zoome * 10 end declare @int1 integer,@d1 numeric(16,1) set @int1 = floor(@num) set @d1 = floor(@num)+0.5 --四舍六入 --5 看尾数和奇偶 if @num>@d1 begin set @result = @int1+1 end else if @num =@d1 begin --看前一位 偶数不变,奇数+1 if @int1 % 2 = 0 set @result = @int1 else set @result = @int1+1 end else set @result = @int1 set @result = @result / @zoome return(@result) end
本人才疏学浅,如果你有更好的方法,欢迎留言讨论.