【问题标题】:Why (int)double.NaN and (int)double.PositiveInfinity are 0?为什么 (int)double.NaN 和 (int)double.PositiveInfinity 为 0?
【发布时间】:2016-10-27 19:31:38
【问题描述】:

C# 中,如果你 0/0 你会得到一个异常。

但如果您使用0.0/00.0/0.0,您将分别得到double.NaNdouble.Infinity

但如果将这些结果转换为 int,则会得到 0。

> (int)double.PositiveInfinity
0
> (int)double.NaN
0

为什么会这样?运行时不应该给出转换错误,因为无穷大显然不是零吗?

【问题讨论】:

  • 你用的是什么工具?在普通应用中,NaN == -2147483648,或使用checked {}时出现异常
  • 在我自己的小应用程序中, (int)Double.NaN 在 x64 机器上为 -1,在 Arm 上为 0。这导致了各种非常奇怪的问题!

标签: c#


【解决方案1】:

这取决于你所处的上下文类型。如果你使用checked 上下文,你会得到一个异常。规范的相关部分是第 6.2.1 节:

对于从 float 或 double 到整数类型的转换,处理取决于发生转换的溢出检查上下文(第 7.6.12 节):

  • 在检查的上下文中,转换过程如下:
    • 如果操作数的值为 NaN 或无穷大,则会引发 System.OverflowException。
    • 否则,源操作数将向零舍入到最接近的整数值。如果这个整数值在目标类型的范围内,那么这个值就是转换的结果。
    • 否则,将引发 System.OverflowException。
  • 在未经检查的上下文中,转换始终成功,并按如下方式进行。
    • 如果操作数的值为 NaN 或无穷大,则转换的结果是目标类型的未指定值。
    • 否则,源操作数将向零舍入到最接近的整数值。如果这个整数值在目标类型的范围内,那么这个值就是转换的结果。
    • 否则,转换的结果是目标类型的未指定值。

因此,在未经检查的上下文中,答案不一定为 0 - 它是未指定的 int 值。事实上,在我的测试中,它在未经检查的上下文中显示为 int.MinValue 而不是 0。

但从根本上说,如果您想进行检查,请使用已检查的上下文(至少对于该表达式)。

【讨论】:

  • @AppDeveloper:我正和 C# 团队的一群工程师坐在一个房间里,所以目前绝对没有这种感觉 :)
  • @AppDeveloper:谁说我有它在内存中?我打开了 C# 规范并搜索了“数字转换”。
  • 对不起,如果我听起来很愚蠢,c# 规范是否可供公众阅读?
  • Jon Skeet:与C# 团队中的工程师 坐在一个房间里,却四处跳来回答问题。
  • @ChrisSinclair:同样,不是 :)
【解决方案2】:

这主要是因为 double.NAN 和 double.PositiveInfity(或 double.Negative )不是数字,而是用于识别概念的值。

当运算结果为未定义时,方法或运算符返回 NaN。例如,零除以零的结果是 NaN,如下例所示。

试试这个来说明这个概念。

if ((0 / zero) == Double.NaN) 
     Console.WriteLine("0 / 0 can be tested with Double.NaN.");
  else 
     Console.WriteLine("0 / 0 cannot be tested with Double.NaN; use Double.IsNan() instead.");

【讨论】:

    猜你喜欢
    • 2015-11-07
    • 2019-12-03
    • 1970-01-01
    • 2017-06-10
    • 1970-01-01
    • 1970-01-01
    • 2019-11-06
    • 2020-12-15
    • 2019-04-22
    相关资源
    最近更新 更多