不同语言的计算精度和范围问题
精度是数字中的数字个数,浮点数在计算机中的表达有限制,不能以任意精度存储
尤其是微小的或巨大的数字在运算时经常会有些意外情况,
在处理大数据的时候,数据量大,其中的一些关于数据量的运算很可能造成结果在少量数据时正常,而在大量数据时运算出现错误的情况。
说明
采用计算机计算数据的时候,数据的精度和数据的范围一定要注意,这方面的问题很隐蔽,在这里总结一下,
计算机是二进制的。浮点数没有办法是用二进制进行精确表示。我们的CPU表示浮点数由两个部分组成:指数和尾数,
这样的表示方法一般都会失去一定的精确度,有些浮点数运算也会产生一定的误差,是实数的无限精度跟计算机的有限内存之间的矛盾
通用语言中的浮点数都是按照 IEEE 754是IEEE二进位浮点数算术标准(IEEE Standard for Floating-Point Arithmetic)
浮点数的格式(包括负零-0)与反常值(denormal number),一些特殊数值(无穷(Inf)与非数值(NaN))
作为常识,不管是JAVA还是其它语言,我们都应该知道:
0.1+0.2 不一定等于0.3 。
1/3 * 3 不一定等于1 。
log2 + log5 也不一写等于1 。
把这个当作常识,精度有点损失似乎就没有影响了--可以在不同的语言中中输入,然后查看结果
C语言
C语言中的计算精度
double
可自行设计算法实现精度的再次升级--这个以后再说吧
Java/Scala
BigInt BigDecimal类来进行计算
BigDecimal,用来对超过16位有效位的数进行精确的运算
BigDecimal对超出16位有效数字的货币值,百分值,以及一般数值进行格式化控制。
在大多数的商业计算中,一般采用java.math.BigDecimal类来进行精确计算。
Java语言中
数学运算和计算机计算的不同之处
数学运算:1/3
计算机运算:1/3.toDouble
计算机运算:1/3.0
Math.floor()返回不大于的最大整数
Math.round()--round方法,它表示“四舍五入”,
算法为Math.floor(x+0.5),即将原来的数字加上0.5后再向下取整,
所以,Math.round(11.5)的结果为12,Math.round(-11.5)的结果为-11。
Math.ceil 则是不小于的最小整数
Scala语言中
数据类型
scala.math.BigInt
scala.math.BigDecimal
//保留两位小数
val a = 3.1415926
val b = a.formatted("%.2f")
举例:
极大值运算
choose() 超过choose(200,160),则会出现问题
def choose(n: Int, k: Int): Int ={
if (k == 0 || k == n) 1
else choose(n - 1, k - 1) + choose(n - 1, k)
}
因为后面的数据会超出Int存储的范围---修改方法,将返回值设为Double
Python
Python默认的是17位精度,也就是小数点后16位
一般的情况,四舍五入和使用格式化控制
math模块的ceil(x) 取大于或者等于x的最小整数。
math模块的floor(x) --
from math import ceil, floor
ceil(2.5)
高精度使用decimal模块,配合getcontext
R 语言
R 语言数据超过千万的时候,要注意数据类型转换 int--numri
Double数据类型中
最大 和最小 1e-316
1/3*3 在R语言里是1 NA(not available)
R语言出现无穷(Inf)与非数值(NaN)的时候,考虑是不是数值计算的原因
默认双精度型数据(double-precision)
floor():向下取整;
ceiling(): 向上取整;
round(): 四舍五入取整;
turnc(): 向0取整;
signif(): 保留给定位数的精度。
注意字符型数值和数字型数值的区别
numeirc
character
SQL语言中
在数值处理功能时,MySQL能给出极其精确的结果,并能对无效值进行高度控制
定义良好的四舍五入特性:对于准确值数值,ROUND()的结果取决于其参量
convert(decimal(8,6),(63883.63/23625))
使用对数值排序的时候,一定要查看数据定义的类型,string也会显示为数字,但是排序方式是有所不同的
注意字符型数值和数字型数值的区别
这个和Excel中文本型数值和数字型数值类似,Excel中还有公式数据。