对double进行转换是否始终返回相同的值?

铸造double float总是产生相同的结果,还是会有一些“四舍五入的差异”?

例如,是x in

 float x = (float)0.123456789d; 

总是一样的价值?

将float浮动为double,然后将其转换为float,即。 (float)(double)someFloat

最感兴趣的是C#中的结果,但如果您对其他语言的工作原理有所了解,请随时分享。

除非语言偏离IEEE规范,否则结果不应取决于语言。

所有浮点数都可以精确地表示为双精度数,因此从float到double到float的往返应该产生与您开始时相同的值。

类似地,将任何double值转换为float应始终产生相同的结果,但是,当然,有许多不同的double值会截断为相同的float值。

如果将double转换为float ,则会丢失精度和数据。 将float向上转换为double转换是一种扩大的转换; 如果然后往返,则不会丢失任何数据…也就是说,除非您在将其向下转换回浮点之前对该值执行某些操作

浮点数会牺牲范围的精度和精度。 单精度浮点数可提供32位精度; 双精度给你64位。 但是它们可以表示超出基础精度指示范围的值。

C# floatdouble是IEEE 754浮点值。

  • float是单精度IEEE 754值 (32位),由a组成

    • 1位符号
    • 8位指数
    • 23位尾数/有效数
  • double是双精度IEEE 754值 (64位)并由a组成

    • 1位符号
    • 11位指数
    • 52位尾数/有效数

尾数的有效精度比其表观大小(浮点魔法)高1位。

一些CLR浮点资源为您服务:

本文可能是关于浮点运算的危险和陷阱的规范性论文。 如果您不是ACM的成员,请单击标题上的链接以查找该文章的公共下载:

  • 大卫戈德伯格。 1991. 每个计算机科学家应该了解浮点运算 。 ACM Comput。 监测网。 23,1(1991年3月),5-48。 DOI = 10.1145 / 103162.103163 http://doi.acm.org/10.1145/103162.103163

    抽象
    浮点运算被许多人视为深奥的主题。 这是相当令人惊讶的,因为浮点在计算机系统中无处不在:几乎每种语言都有浮点数据类型; 从PC到超级计算机的计算机都有浮点加速器; 大多数编译器都会被要求不时编译浮点算法; 几乎每个操作系统都必须响应溢出等浮点exception。 本文提供了一个关于浮点方面的教程,它对计算机系统的设计者有直接影响。 它首先介绍了浮点表示和舍入误差,继续讨论IEEE浮点标准,最后给出了计算机系统构建器如何更好地支持浮点的示例。

double应该能够准确地保存float的每个可能值。 将float转换为double不应更改该值,并且只要您在此期间未对double执行任何计算,则返回到float应返回原始值。

考虑到它们具有不同的精度,即使我从较低精度到较宽精度(我认为这实际上是您的怀疑),结果也不一定相同。

浮点运算,尤其是转换,总是截断/舍入和任何其他类型的近似

在某些情况下,与数字量最接近的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,所以即使在转换为double然后float失去精度的情况下,通过直接指定数字作为float也无法避免这种转换损失。

顺便提及,值12344321.4999999992f和12345678.50000000094f被正确舍入。

C#中的浮点数使用IEEE 754格式(http://en.wikipedia.org/wiki/IEEE_754)存储。 这种格式有两部分:数字和指数。 双打保持52位数,浮动保持23位数。 基数是2,而不是10。 因此,对于上面的示例(0.123456789),数字将是111010110111100110100010101(123456789的二进制表示)。 那是27位数,它很适合双倍,但不是浮点数,所以是的,精确度会在往返转换中丢失。

另一方面,如果您的数字是0.123456,则数字将是11110001001000000(17位数),它可以很好地适合浮点数或小数,因此您在往返投射中将失去精确度。