float _original_1 = 5.2f;
Console.WriteLine("原始数据:"+ _original_1);
Console.WriteLine("原始数据强转byte:" + (byte)(_original_1 * 10.000f));
Console.WriteLine("原始数据强转Short:" + (short)(_original_1 * 100.000f));
Console.WriteLine("原始数据强转Int:" + (int)(_original_1 * 1000.000f));
1,首先先看上面的代码,输出结果并非预料中的52 和520!而是:
原始数据:5.2
原始数据强转byte:51
原始数据强转Short:519
原始数据强转Int:5199
2, float精度丢失了,为什么呢?找到两篇帮助理解的文章:
float转换为二进制的存储方式:1位符号位, 8位指数移码 ,23位尾数
int型数据转换成float型精度丢失的问题, 明明float的表示范围更大怎么会丢失精度呢?
由上边的浮点数存储方式可以看出,32位浮点数有23位来拓展精度, int型整数4个字节,31位(1位符号位)全部用来拓展精度, 当int表示的数超过float所能表示的精度时, 只能靠丢失精度来近似表示了。
(1)十进制整数如何转化为二进制数
算法很简单。举个例子,11表示成二进制数:
11/2=5 余 1
5/2=2 余 1 2/2=1 余 0
1/2=0 余 1
0结束
11二进制表示为(从下往上):1011
这里提一点:只要遇到除以后的结果为0了就结束了,大家想一想,所有的整数除以2是不是一定能够最终得到0。换句话说,所有的整数转变为二进制数的算法会不会无限循环下去呢?绝对不会,整数永远可以用二进制精确表示 ,但小数就不一定了。
(2)十进制小数如何转化为二进制数
算法是乘以2直到没有了小数为止。举个例子,0.9表示成二进制数
0.9*2=1.8 取整数部分 1
0.8(1.8的小数部分)*2=1.6 取整数部分 1
0.6*2=1.2 取整数部分 1
0.2*2=0.4 取整数部分 0
0.4*2=0.8 取整数部分 0
0.8*2=1.6 取整数部分 1
0.6*2=1.2 取整数部分 0
.........
0.9二进制表示为(从上往下): 1100100100100......
注意:上面的计算过程循环了,也就是说*2永远不可能消灭小数部分,这样算法将无限下去。很显然,小数的二进制表示有时是不可能精确的 。其实道理很简单,十进制系统中能不能准确表示出1/3呢?同样二进制系统也无法准确表示1/10。这也就解释了为什么浮点型减法出现了"减不尽"的精度丢失问题。
3,怎么解决这个问题
就要用到 Convert这个类,将一个数据基本类型转换为另一个数据基本类型!(强烈推荐)
Console.WriteLine("原始数据Convert强转byte:" + Convert.ToByte(_original_1 * 10.0f));
Console.WriteLine("原始数据Convert强转short:" + Convert.ToUInt16(_original_1 * 100.00f));
Console.WriteLine("原始数据Convert强转short:" + Convert.ToInt32(_original_1 * 100.00f));
原始数据:5.2
原始数据Convert强转byte:52
原始数据Convert强转short:520
原始数据Convert强转short:520
或者可以将计算的数字转换为string型,因为string是确定的!
Console.WriteLine("原始数据强转byte:" + byte.Parse((_original_1 * 10.000f).ToString()));
Console.WriteLine("原始数据强转Short:" + short.Parse((_original_1 * 100.000f).ToString()));
Console.WriteLine("原始数据强转Int:" + int.Parse((_original_1 * 1000.000f).ToString()));
原始数据:5.2
原始数据byte.Parse:52
原始数据short.Parse:520
原始数据int.Parse:5200
当时要注意用byte.Parse时()方法后不能有小数,不然会报:输入字符串的格式不正确的错误!也就是说若我的原始数据为5.25(两个小数时,需要*100)。
用Convert类转换就不需要担心这个了!