代码之家  ›  专栏  ›  技术社区  ›  brainimus user417509

为什么把一个NaN转换成一个long会产生一个有效的结果?

c#
  •  21
  • brainimus user417509  · 技术社区  · 14 年前

    在下面的示例代码中,我将除以0,当我使用调试器遍历它时,(除数/除数)将产生无穷大或NaN(如果除数为零)。当我将这个结果转换为long时,我得到一个有效的结果,通常类似于-9223372036854775808。为什么这个演员有效?为什么它不停止执行(例如抛出一个异常)而不是分配一个任意值?

    double divisor = 0;
    double dividend = 7;
    long result = (long)(dividend / divisor);
    
    5 回复  |  直到 14 年前
        1
  •  24
  •   Eric Lippert    14 年前

    为什么这个演员有效?

    可以 成功或 总是 成功。只有当转换不可能成功时,强制转换才是非法的(例如,将密封类型强制转换为它没有实现的接口。)从double到long的转换可能会成功。因此,演员阵容是有效的。

    为什么它不停止执行(例如抛出一个异常)而不是分配一个任意值?

    因为你没有要求例外!规范非常清楚预期的行为是什么。见第6.2.1节:

    在选中的上下文中,转换过程如下:

    [...]

    您正在未检查的上下文中执行代码;你没有要求任何例外,所以你没有例外。如果你想要一个例外,就要求一个例外;使用选中的上下文。

        2
  •  14
  •   SLaks    14 年前

    你可以使用 checked block 强制运行时检查溢出并抛出异常,如下所示:

    checked {
        double divisor = 0;
        double dividend = 7;
    
        long result = (long)(dividend / divisor);
    }
    

    请注意,将有轻微的性能损失。

        3
  •  11
  •   Hans Passant    13 年前

    C语言规范第6.2.1节明确记录了该行为:

    对于从float或double到integral类型的转换 转换发生在:

    在选中的上下文中,转换过程如下:

    • 抛出System.OverflowException。
    • 最近的整数值。如果该整数值在 目标类型则此值是转换的结果。

    如下所示。

    • 如果操作数的值为NaN或无穷大,则 转换是目标类型的未指定值。
    • 否则,源操作数将向零舍入为零 最近的整数值。如果该整数值在 目标类型则此值是转换的结果。
    • 否则,转换的结果是 目标类型。

        4
  •  4
  •   Jakob    14 年前

    您还可以在编译时使用“checked”标志,其工作方式与将所有代码包装到checked块中的方式相同。

        5
  •  3
  •   kemiller2002    14 年前

    这取决于数据类型。对于被零除,不同的数据类型将有不同的结果。

    http://blogs.msdn.com/rafats/archive/2006/07/20/673337.aspx

    http://www.eggheadcafe.com/software/aspnet/30920566/divide-by-zero-question.aspx

    来自另一个网站的Jon Skeet(以上链接):

    一句话,标准。至少,我怀疑这就是原因。 浮点/双精度运算遵循IEC 60559标准算术规则, 引发异常。

    十进制没有(或者至少没有) to-C规范允许的可能性)支持“无限” 值浮动/双do。相似 decimal没有指定NaN。

    除零说明: http://www.philforhumanity.com/How_to_Divide_by_Zero.html