将 double
强制转换为 float
是否总是产生相同的结果,还是可能存在一些“舍入差异”?
例如,在下面的代码中,x
是否始终等于 y
?
float x = (float)0.123456789d;
转换回去的值是否总是相同?
当将float转换为double,然后再将其转换回float时,情况如何,例如:(float)(double)someFloat
?
我最感兴趣的是在C#中的结果是什么,但如果您了解其他语言中的工作原理,请随意分享。
将 double
强制转换为 float
是否总是产生相同的结果,还是可能存在一些“舍入差异”?
例如,在下面的代码中,x
是否始终等于 y
?
float x = (float)0.123456789d;
转换回去的值是否总是相同?
当将float转换为double,然后再将其转换回float时,情况如何,例如:(float)(double)someFloat
?
我最感兴趣的是在C#中的结果是什么,但如果您了解其他语言中的工作原理,请随意分享。
float
是单精度IEEE 754值(32位),由以下内容组成:
double
是双精度IEEE 754值(64位),由以下内容组成:
尾数的有效精度比它的表面大小高1个比特(浮点数魔法)。
一些CLR浮点数资源供您使用:
摘要
浮点运算被许多人认为是一门神秘的学科。这相当令人惊讶,因为浮点在计算机系统中无处不在:几乎每种语言都有浮点数据类型;从个人电脑到超级计算机都有浮点加速器;大多数编译器都会不时地编译浮点算法;而且几乎每个操作系统都必须响应浮点异常,例如溢出。本文介绍了与计算机系统设计师直接相关的浮点方面的教程。它从浮点表示和舍入误差的背景开始,继续讨论IEEE浮点标准,并以计算机系统构建者如何更好地支持浮点为例结束。
float
表示可能与将最接近的double
表示四舍五入为float
所得到的值不同。两个这样的量是12,344,321.4999999991和12,345,678.50000000093。上下整数都可以精确地表示为float
,但是最接近它们的double
的小数部分恰好为0.5。因为将这样的double
值(介于2^23和2^24之间,小数部分恰好为0.5)转换为float
会四舍五入到最接近的偶数;编译器在每种情况下最终都会向远离原始数字更近的值四舍五入。double
,然后转换为float
,因此即使12344321.4999999991f应该四舍五入为12344321f,它仍会四舍五入为12344322f。同样,12345678.50000000093f应该四舍五入为12345679f,但它却四舍五入为12345678f,因此即使将数字直接指定为float
,也无法避免由于转换为double
然后float
而失去精度的情况。(double)4.123401f
在标准的ToString()
中等于4.12340116500854
。这不是同一个数字。无论使用与否,在双精度单元格中的数字都不相同。 - Tigran01000000100000111111001011100111
,double值为0100000000010000011111100101110011100000000000000000000000000000
;这些值完全相等。ToString输出的差异是因为float.ToString()将其输出四舍五入到较少的小数位数,而double.ToString()则不会。 - phoog0.123456789d
的二进制表示实际上是0011111110111111100110101101110100110111001110010110001101011111
;尾数为(1).1111100110101101110100110111001110010110001101011111
。相应的浮点值为00111101111111001101011011101010
(尾数为(1).11111001101011011101010
)。由于123456789/1000000000
在二进制中无限重复,因此这两个值都不适合双精度甚至单精度,容量太小了。 - phoog
d
是表示双精度浮点型 (double)。M
表示十进制数值类型(缩写为 "money")。http://msdn.microsoft.com/zh-cn/library/bfft1t3c.aspx - Mr Lister