文章目录
- 二进制的小数
- 无法转换的小数
- 浮点数
- 如何保证计算的精度
- 回避策略
- 把小数转换成整数来计算
- BCD编码方式
- 十六进制的使用
二进制的小数
规则:小数点后面部分的位权,第 1 位是 2 的-1 次幂、第 2 位是 2 的-2 次幂
这一规律并不仅限于二进制数,在十进制数和十六进制数中也同样适用
例子:
将 1011.0011 转换为十进制的数?
图:
负指数幂的推导
图:
0 指数幂推导
零指数幂推导:
图:
无法转换的小数
//result = 10.000002
public static void show1(){
float sum = 0;
int i;
for(i = 0; i < 100; i++){
sum += 0.1;
}
System.out.println(sum);
}
二进制数转换为十进制小数对应表:
图:
原因汇总:
(1)计算机这个功能有限的机器设备,是无法处理无限循环的小数的
(2)不管增加多少位, 2 的-○○次幂怎么相加都无法得到 0.1 这个结果(确实存在无法转换)
(3)无法用十进制数来表示 1/3 是一样的道理。1/3 就是 0.3333…
浮点数
分类:
双精度浮点数类型用 64 位
单精度浮点数类型用 32 位来表示全体小数
浮点数具体组成:
浮点数是指用符号、尾数、基数和指数这四部分来表示的小数
图:
引用:双 精 度 浮 点 数 能 够 表 示 的 正 数 范 围 是 4.94065645841247×10-324~1.79769313486232×10 308 ,负 数 范 围 是-1.79769313486232×10 308 ~ -4.94065645841247×10-324 。 单 精 度 浮 点 数 能 够 表 示 的 正 数 范 围 是1.401298×10 -45 ~3.402823×10 38 ,负数范围是-3.402823×10 38 ~-1.401298×10-45 。
不过,正如正文中所介绍的那样,在这些范围中,有些数值是无法正确表示的
符号部分: 是指使用一个数据位来表示数值的符号。该数据位是 1时表示负,为 0 时则表示“正或者 0”。
尾数部分: 用的是“将小数点前面的值固定为 1 的正则表达式”
图:
正则表达式:按照特定的规则来表示数据的形式即为正则表达式。除小数之外,字符串以及数据库等
指数部分: 用的则是“EXCESS 系统表现”
好处:使用 8 位二进制数 00000000 - 11111111(十进制数 255)就能够表示对应的正、负情况了
对应图:
如何保证计算的精度
回避策略
无视这些错误。根据程序目的的不同,有时一些微小的偏差并不会造成什么问题
例如:
假设使用计算机设计工业制品。将 100 个长 0.1 毫米的零件连接起来后,其长度并非一定要是10 毫米,10.000002 毫米也没有任何问题。一般来讲,在科学技术计算领域,计算机的计算结果只要能得到近似值就足够了。那些微小的误差完全可以忽略掉
把小数转换成整数来计算
分析:计算机在进行小数计算时可能会出错,但进行整数计算(只要不超过可处理的数值范围)时一定不会出现问题
实例:
Decimal的原理就是把小数放大10的N次方倍,将小数点移动到后面,这样利用都是整数,就保证了精度。
BigDecimal 由任意精度的整数非标度值 和32 位的整数标度 (scale) 组成。如果为零或正数,则标度是小数点后的位数。如果为负数,则将该数的非标度值乘以 10 的负scale 次幂。因此,BigDecimal表示的数值是(unscaledValue × 10-scale)。
BCD编码方式
定义:8421 BCD码是最基本和最常用的BCD码,它和四位自然二进制码相似,各位的权值为8、4、2、1,故称为有权BCD码。和四位自然二进制码不同的是,它只选用了四位二进制码中前10组代码,即用0000~1001分别代表它所对应的十进制数,余下的六组代码不用
好处:相对于一般的浮点式记数法,采用BCD码,既可保存数值的精确度,又可免去使计算机作浮点运算时所耗费的时间。
例如:”93.14“
9用4位二进制数码表示为:1001
3用4位二进制数码表示为:0011
1用4位二进制数码表示为:0001
4用4位二进制数码表示为:0100
组合得到93.14得BCD码:10010011.00010100
思路:因为可以精确的使用二进制数字表示了十进制的数了,那么相应的四则运算自然亦不成问题
十六进制的使用
方式:只需在数值的开头加上 0x(0 和 x)就可以表示十六进制数
好处:通过使用十六进制数,二进制数的位数能够缩短至原来的 1/4。位数变少之后,看起来也就更清晰了
摘取BigDecima 源码展示:
private static final long[][] LONGLONG_TEN_POWERS_TABLE = {
{ 0L, 0x8AC7230489E80000L }, //10^19
{ 0x5L, 0x6bc75e2d63100000L }, //10^20
{ 0x36L, 0x35c9adc5dea00000L }, //10^21
{ 0x21eL, 0x19e0c9bab2400000L }, //10^22
{ 0x152dL, 0x02c7e14af6800000L }, //10^23
{ 0xd3c2L, 0x1bcecceda1000000L }, //10^24
{ 0x84595L, 0x161401484a000000L }, //10^25
{ 0x52b7d2L, 0xdcc80cd2e4000000L }, //10^26
{ 0x33b2e3cL, 0x9fd0803ce8000000L }, //10^27
{ 0x204fce5eL, 0x3e25026110000000L }, //10^28
{ 0x1431e0faeL, 0x6d7217caa0000000L }, //10^29
{ 0xc9f2c9cd0L, 0x4674edea40000000L }, //10^30
{ 0x7e37be2022L, 0xc0914b2680000000L }, //10^31
{ 0x4ee2d6d415bL, 0x85acef8100000000L }, //10^32
{ 0x314dc6448d93L, 0x38c15b0a00000000L }, //10^33
{ 0x1ed09bead87c0L, 0x378d8e6400000000L }, //10^34
{ 0x13426172c74d82L, 0x2b878fe800000000L }, //10^35
{ 0xc097ce7bc90715L, 0xb34b9f1000000000L }, //10^36
{ 0x785ee10d5da46d9L, 0x00f436a000000000L }, //10^37
{ 0x4b3b4ca85a86c47aL, 0x098a224000000000L }, //10^38
};