读书人

ruby编程中精度有关问题的总结

发布时间: 2012-08-26 16:48:05 作者: rapoo

ruby编程中精度问题的总结
最近半年一直在开发一个跟金融相关的互联网应用,金融的计算要求严谨,数字相差一分钱也会给用户产生不够专业不值得信任的感觉。结合ruby编程语言,谈一下计算的精度问题。引用精确计算的前提,是区分数值是中间量还是输入输出量,输出量做为一个给用户看到的量,是有效力的,在四舍五入后得到量,只要是会被用户看到了解到的,在后面的计算中就应该做为一个精确量。
举例:A有1.01元,分给B,C,他们均只能拿到0.5元,B要再给D钱,就应该以0.5为依据,而不是0.505。
引用所以计算的过程可以概括为:
输入量----》中间计算过程,误差在累积----》保留确定位数的小小数,输出----》输出作为精确输入量再次输入----》中间计算过程,误差累积---》.....
这个过程的重复。
要保证计算的精度,就是要保证中间计算过程中误差累积不要超过输出的精度要求。也就是说,中间计算过程不要积累太多的误差就OK了。
对于能精确到小数点后面q位的数据类型,误差最大为10^(q+1)*5,例如:只能精确2位小数数据类型,误差最大为0.005。设最大误差为p,误差的积累情况如下:
X1+X2+....+Xn的形式,最大误差<=n*pX1*n,误差<=n*pX1^n,误差<=n*p
上面都很容易证明。
下面的各种数据类型误差累积做一个简单分析。
1.IEEE浮点书,分为single,double,分别为32,64位,32位的进度为十进制小数点后6位,64位为14位,例如,对于32位的情况,如要球精度为2位小数,只要保证前面的计算情况下n<10000即可。ruby 中的float为64位IEEE浮点数。这种类型还会有10进制转化2进制的还有误差,如0.2就会有误差。
2.类似Bignum这样的类型,可以表示任意精度的整数,把这个思想运用到浮点数,能个解决进制转化带来的精度问题,还对于很多运算,还是有误差,比如1 / 3的情况,必然还是会产生3*10^(-n)的误差。ruby中的bigdecimal,整数部分精度是无限的,是一个Bignum,小数部分18位。
3.要解决2中有理数运算产生的误差问题,还可以使用rational类型,但这个对于如PMT这样的函数,会产生无理数的,还是会有误差。
还有一种自然尾损尾溢的情况,还是如上例,有1分钱不知道去哪里,这个不是计算精度的问题,因为大家有分来做资金结算的最小单位产生的自然的尾损问题。这种情况也是值得注意的。

读书人网 >编程

热点推荐