算法:四舍六入五成双 ,保留三位有效数字

本文探讨了在实际生产制造统计中数值计算的精度丢失问题,并介绍了一种改进的计算方式——四舍六入无成双法则。通过C#代码实现,确保整体数据的准确性和平均性。此外,提供了SQL实现版本,展示了如何在数据库层面应用此方法。最后,作者邀请读者分享更多优化建议。

     在实际的生产制造统计中,会有精度丢失的情况. 倘若按照 我们平常所用的 四舍五入,(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;

}
View Code

 

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 
View Code

 

  本人才疏学浅,如果你有更好的方法,欢迎留言讨论.

 

转载于:https://www.cnblogs.com/mjxxsc/p/4048715.html

sqlserver函数实现五成保留指定数小数数。 含义编辑 对于数很多的近似数,当有效数确定后,其后面多余的数字应该去,只保留有效数字最末一,这种修约()规则是“五成”,也即“465凑偶”,这里“”是指≤4 时去,""是指≥6时进上,"五"指的是根据5后面的数字来定,当5后有数时,51;当5后无有效数字时,需要分两种情况来讲: (1)5前为奇数,51; (2)5前为偶数,5不进(0是偶数)。 具体规则编辑 (1)被修约的数字小于5时,该数字去; (2)被修约的数字大于5时,则进; (3)被修约的数字等于5时,要看5前面的数字,若是奇数则进,若是偶数则将5掉,即修约后末尾数字都成为偶数;若5的后面还有不为“0”的任何数,则此时无论5的前面是奇数还是偶数,均应进。 举例编辑 举例,用上述规则对下列数据保留3有效数字: 9.8249=9.82, 9.82671=9.83 9.8350=9.84, 9.83501=9.84 9.8250=9.82, 9.82501=9.83 从统计学的角度,“五成”比“”要科学,在大量运算时,它使后的结果误差的均值趋于零,而不是像那样逢五就,导致结果偏向大数,使得误差产生积累进而产生系统误差,“五成”使测量结果受到误差的影响降到最低。 例如:1.15+1.25+1.35+1.45=5.2,若按取一小数计算: 1.2+1.3+1.4+1.5=5.4 按“五成”计算,1.2+1.2+1.4+1.4=5.2,后的结果更能反映实际结果。 尤其是在化学领域应用广泛,在计算“分析化学”、“化学平衡”时经常需要使用“五成”这种较精确的修约方法。这样得到的结果较精确,而且运算量相对来说也不大,十分有用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值