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


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

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

  • 相关阅读:
    Linux常用解压文件
    微信开放平台 获取 component_verify_ticket
    mysql root密码重置
    编译安装LNMP
    JS生成二维码
    CURL采集
    JS拖动浮动DIV
    JS拖动DIV布局
    Nginx 反向代理、负载均衡、页面缓存、URL重写及读写分离详解
    zepto.js 源码注释备份
  • 原文地址:https://www.cnblogs.com/mjxxsc/p/4048715.html
Copyright © 2020-2023  润新知