`
uuu999ggg
  • 浏览: 41828 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

int, float, double之间不得不说的故事

 
阅读更多

int整型: .net中特指Int32为32位长度符号整型变量

float:单精度浮点数32位长度1位符号位8位指数位与23位数据位 .net中又称为Single

double:64位长度双精度浮点数1位符号位11位指数位52位数据位

它们互相关系就:int可以稳式转换成float和double,float只能强制转换成int但可以隐式转换成double,double只能强制转换成float和int

 

 
  废话说完这就出现了几个困难而且比较意思困难

  1 int i = Int32.MaxValue;

  2 float f = i;

  3 int j = (int)f;

  4 bool b = i == j;

  这里b=false。刚才这个操作,如果我们把float换成long,第一次进行隐式转换,第二次进行强制转换结果将会true。乍一看float.MaxValue比int.MaxValue大了不知道多少倍,然而这个隐式转换中却造成了数据丢失。int.MaxValue这个值等于2^31-1,写成二进制补码形式就01111…(31个1)。这个数表示成float计数科学计数法时候将会写成+0.1111…(23个1)*2^31。对于那31个1里面最后8个被float无情抛弃了。因此再将这个float强制转换回int时候,对应int二进制补码表示已经变成了0111…(23个1)00000000。这个数与最初那个int相差了255,所以造成了不相等。

  那么提出另一个困难,嘛样int变成float再变回来和从前值相等呢?这个困难其实完全出那23位float数据位上了。对于一个int把它写成二进制形式之后成为了个一32个长度0、1排列对于这个排列只要第一个1与最后一个1之前间距不超过23,那么它转换成float再转换回来两个值就会相等。这个困难与大小无关而且这个集合int这个全集下并不连续。

  1 double d = 0.6;

  2 float f = (float)d;

  3 double d2 = f;

  4 bool b = d == d2;

  这里b也false。刚才这个操作如果开始另d等于0.5结果就将会true。乍一看0.6这个数这么短,double和float都肯定能够表示那么转换过去,再转换回来结果理应相等。其实这因为我们用十进制思考困难太久了。如果我们0.6化成二进制小数,可以发现得到结果0.10011001……(1001循环)这一个无限循环小数。因此不管float还double它存储0.6时候都无法完全保存它精确值(计算机不懂分数呵呵)。这样话由于float保存23位,而double保存52位,就造成了double转化成float时候丢失掉了一定数据,再转换回去时候那些丢掉值被补成了0。因此这个后来double和从前double值已经不再一样了。

  这样就又产生了一个困难,嘛样double转换成float再转换回来两个值相等呢?其实这个困难与刚才int那个困难惊人相似(废话都和float打交道能不相似么)只不过我们还需要考虑double比float多了3位指数位,太大数double能表示但float不行。

  还一个算数学上困难嘛样十进制小数表示成二进制不无限小数呢?这个困难可以说完全成为数学范畴内困难了,但比较简单,答案也很明显。对于所最后一位以5结尾十进制限小数都可以化成二进制限小数(虽然这个小数可能长到没谱)。

  最后一个意思困难,刚才说过0.6表示成为二进制小数之后0.1001并且以1001为循环节无限循环小数,那么我们将它存成浮点数时候一定会某个位置将它截断(比如float23位和double52位)。那么真正存内存里这个二进制数转化回十进制到底比原先十进制数大呢还小呢?答案It depends。人计算十进制时候四舍五入,计算机再计算二进制小数也挺简单就0舍1入。对于float要截断成为23位,假如卡24位上1那么就会造成进位,这样话存起来值就比真正十进制值大了。如果0就舍去,那么存起来值就比真正十进制值小了。因此这可以合理解释一个困难,就0.6d转换成float再转换回double,它值0.60000002384185791这个值比0.6大,解释就0.6二进制科学计数法表示第24位1造成了进位

  到了这里仍然一事不解,就对于浮点数硬件虽然给予了计算上支持但它与十进制之间互相转换到底怎么样做到呢。又谁做呢(汇编器还编译器)这个东西突出体现存内存里数明显实际与0.6不等但无论哪种语言都能够Debug以及输入时候将它正确显示成0.6提供给用户(源代码员)。最好实例就double和ToString办法如果我写double d=0.59999999999999999999999999999d.ToString()给我0.6。诚然对于double来说,我写那个N长数与0.6内存里存东西一样,但计算机又如果处理方案了,将一个实际与0.6不相等数变回0.6并显示给我呢?关于这个困难欢迎大家讨论并请高手指教一二?

转自http://www.aicuxiao.com/code/view2358.html

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics