如何检查一个double能否在不转换为无穷大的情况下适合于float?

3

有没有一种标准的方法来检查64位浮点数是否可以转换为32位而不需被转换为+/-无穷大?

我知道之后可以检查+/- Inf。

Convert.ToSingle()无法实现此操作。


2
不比较 Single.MinValueSingle.MaxValue 有帮助吗?http://msdn.microsoft.com/en-us/library/system.single.minvalue.aspx - Knaģis
1
@Knaģis 在 Single.MaxValue 上方的一些双精度数会转换为 Single.MaxValue。有关浮点数的这个方面的讨论,请参阅此帖子的“Polyspace”部分:http://blog.frama-c.com/index.php?post/2011/11/25/Static-analysis-tools-comparisons - Pascal Cuoq
1个回答

3
为了测试一个 double 类型的值 d 是否可以转换为 float 类型而不产生无穷大,你可以测试 d 的绝对值是否严格小于 3.4028235677973366e+38 这个十六进制表示中的 0x1.ffffffp+127,这个数是可以转换为 float 类型和不能转换为 float 类型之间的精确分界线。
稍微扩展一下,最后一个有限的 float 值是:
0x1.fffffep+127   (3.4028234663852886e+38 in decimal)

如果 float 类型有更多的指数位,下一个 float 数字将会是什么:
0x2.000000p+127   (3.4028236692093846e+38 in decimal)

距离前一个数字比后一个数字更近的数字会被舍入为前一个数字。极限是两个数字的中点:

0x1.ffffffp+127   (3.4028235677973366e+38 in decimal)

2
@IanC 你说得对,我的值略高。Single.MaxValue 是最后一个有限单精度浮点数,但在“四舍五入”模式下,一些比这个数字大的值被认为是向下舍入到它,因为它是“最近的”。确切的极限是介于 Single.MaxValue 和如果有更多指数位将是下一个 float 值之间的中间值。 - Pascal Cuoq
测试溢出的确切值难道不应该是Single.MaxValue加上足够大的epsilon以获取下一个double(而不是float)的值吗? - IamIC
3.4028234663852888E+38 - IamIC
更正:在C#中,针对内置常量进行测试总是有效的。 - IamIC
1
我的答案是对(float)test == +inf进行精确测试,根据浮点数标准中明确定义的舍入规则。与Single.MaxValue比较是安全的,因为它永远不会回答“true”对于一个会产生无穷大的数字,但它拒绝了一些根据规则将被转换为有限浮点数的值。这只是一个非常小的差异,你不必担心,我只是坚持这样做,因为我不想让你留下浮点数不可靠的印象。 - Pascal Cuoq
显示剩余16条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接