.Net业务平台的数值精度陷阱与解决方法_.Net教程
推荐:ASP.NET中用healthMonitor属性用法在ASP.NET 2.0中,可以使用healthMonitoring属性监测事件。healthMonitoring属性是一个基于方法的provider,在这里可以构造自己的provider。利用healthMonitoring属性,我们可以诸如记录错语、
本文主要介绍一下.Net业务平台的数值精度陷阱与解决方法。
最近公司的实施人员反映,数量小数位保留3位精度不够,需要保留6位才行,回想起这个问题,公司开发上线的ERP系统,数量,金额,成本的计算方式反反复复都修改过好多次,以前都没有对这个业务规则进行计算封装,和统一指定规则,修改就成了一件多而繁琐的的事情了;现在深刻体会这些业务细节将会对业务系统的运行是非常重要的,而业务系统规则的明晰和好的系统业务架构是对其的保证。
修改过程是一个渐进的过程,希望有过次这方面经验的朋友提提建议,也希望没有注意到这些细节的朋友少走弯路,简单归纳了下,产生错误地方有3个方面:
最先意识到的是计算精度丢失,主要是这几个原因引起的:
1、查看后台代码的发现代码里有有变量是用的float或double类型,这样精度在计算的时候就会有精度转换误差,这个比较容易解决,都改为decimal 类型就可以了;
2、是发现有很多计算的精度丢失是因为使用到中间变量的原因,而在中间变量有保留小数位!现在修改方式第一种方式是中间变量的精度尽可能长,第二方式是直接用原始变量来计算最终结果。
3、有部分计算是js来计算的,因为js里没有decimal类型的变量,这种常常会产生精度丢失,需要最后ToFix()下保留精度。
第二方面是存储的数值的精度丢失,是因为数字类型未设置正确, 如设置成float ,double 类型都可能有转换精度丢失,decimal类型没有暂时没有在系统中使用过。也有种情况是中间小数位精度不够长,数值如果用于再次计算的时候,也将出现精度不够的情况。我们现在一般都需要设置数字类型为numerice,数量保留6位小数,显示金额保留2位,计算成本保留8位小数。
第三方面是显示的问题,在某些特定的地方,需要显示小数位去除多余的0, 一般存在于是报表的显示,和页面显示比较拥挤的地方。在报表里最简便的方法是,利用公式字段去除显示多余的0。
设置方法如下:
选择需要格式化的字段, 选“自定义样式”,在“四舍五入”里选择0.0001,然后点“十位”后面的按钮,输入以下公式:
以下为引用的内容: if Right (ToText ({命令_4.PartNum}, 6), 6) = "000000" then 0 else if Right (ToText ({命令_4.PartNum}, 6), 5) = "00000" then 1 else if Right (ToText ({命令_4.PartNum}, 6), 4) = "0000" then 2 else if Right (ToText ({命令_4.PartNum}, 6), 3) = "000" then 3 else if Right (ToText ({命令_4.PartNum}, 6), 2) = "00" then 4 else if Right (ToText ({命令_4.PartNum}, 6), 1) = "0" then 5 else 6 |
可以实现数字保留6位精度,如果数值有0 的地方自动去除掉多余的0
设置步骤如下图(里面公式稍稍有不一样,但是都可以实现结果):
也可以用修改Sql的方式去除多余的小数位0。
以下为引用的内容: SELECT col, col_convert = CASE WHEN CHARINDEX('.', col) = 0 THEN col WHEN RIGHT(col, PATINDEX('%[^0]%', REVERSE(col))) LIKE '.%' THEN LEFT(col, LEN(col) - PATINDEX('%[^0]%', REVERSE(col))) ELSE LEFT(col, LEN(col) - PATINDEX('%[^0]%', REVERSE(col)) 1) END FROM( SELECT col = '100' UNION ALL SELECT col = NULL UNION ALL SELECT col = '.100' UNION ALL SELECT col = '.100100' UNION ALL SELECT col = '0.' UNION ALL SELECT col = '0' UNION ALL SELECT col = '100.1010' UNION ALL SELECT col = '100.0000' )A |
可以简单对这个sql封装成函数来实现;
最后还值得注意的有3点:
1、很多数值不正确是因为计算公式或逻辑不明确引起的,有些代码是没有真正理解清楚就开始在开发了;ERP系统的开发对业务的逻辑理解是非常重要的;
2、后台显示去除0的方法也有一种是,在程序里直接double.Parse()下就可以去除掉小数位多余的0,再ToString()为字符显示,double类型有个问题,如果数字为连续的5位小数0,就会显示为自动缩变为科学计算法,如果是后台显示的地方,可以先double.parse()下,转为string,再转为decimal类型就会去除掉多余的小数位0了。
3、最先我们把数量保留3位精度,金额保留2位,和成本保留4精度,后来发现实际业务计算的时候是不够的,应该早考虑这方面的业务规则定义和计算,可以使用Excel或类似的工具来早与客户,架构师,程序员,测试员之间沟通;
分享:转换DataSet到普通xml的新法大家知道,用dataset传递的WebService,微软会在各个节点加上schema,所以无法与j2ee,flash兼容,所以我找到了一种转换他们变成普通xml的方法。代码如下: 方法一:
- asp.net如何得到GRIDVIEW中某行某列值的方法
- .net SMTP发送Email实例(可带附件)
- js实现广告漂浮效果的小例子
- asp.net Repeater 数据绑定的具体实现
- Asp.Net 无刷新文件上传并显示进度条的实现方法及思路
- Asp.net获取客户端IP常见代码存在的伪造IP问题探讨
- VS2010 水晶报表的使用方法
- ASP.NET中操作SQL数据库(连接字符串的配置及获取)
- asp.net页面传值测试实例代码
- DataGridView - DataGridViewCheckBoxCell的使用介绍
- asp.net中javascript的引用(直接引入和间接引入)
- 三层+存储过程实现分页示例代码
- 相关链接:
- 教程说明:
.Net教程-.Net业务平台的数值精度陷阱与解决方法。