C#做浮点除法的代码在哪里?

Where is the code that does floating-point division for C#?

问题

我想看看除以零时进行浮点除法和 returns Infinity 的代码段。我在哪里可以找到它?

代码示例

想知道的动机来自从 .NET 文档中获取的这段代码。我本来希望得到 DivideByZeroException 但我得到 Infinity.

https://docs.microsoft.com/en-us/dotnet/api/system.dividebyzeroexception?view=netframework-4.8#remarks

using System;

public class Example
{
   public static void Main()
   {
      int number1 = 3000;
      int number2 = 0;

      Console.WriteLine((double)number1 / number2);
   }
}
// The example displays the following output:
//        Infinity

文档

我发现文档说明浮点数除以零不会抛出异常,所以没关系:

https://docs.microsoft.com/en-us/dotnet/api/system.dividebyzeroexception?view=netframework-4.8#remarks

Dividing a floating-point value by zero doesn't throw an exception; it results in positive infinity, negative infinity, or not a number (NaN), according to the rules of IEEE 754 arithmetic. Because the following example uses floating-point division rather than integer division, the operation does not throw a DivideByZeroException exception.

.NET Framework 中的代码

在 Visual Studio 中,我将鼠标悬停在“/”分隔符上,Resharper 显示

double double.operator /(double left, double right)

现在,我想看看它的实现,看看 Infinity 是如何返回的。但是我找不到。

我在这里查看了

但看不到除法运算符。

以上link那带我来

但也没有实现细节。

我也看过这里

但只能看到注释掉的代码

///        Double IArithmetic<Double>.Divide(Double divisor, out bool overflowed) {
///            Double s = m_value / divisor;
///            overflowed = IsInfinity(s) || IsNaN(s);
///            return s;
///        }

corefxDouble 实现中也没有任何内容:

我会期待这样的东西(伪代码):

public static double operator /(double left, double right)
{
   if (right == 0)
   {
      return double.Infinity;
   }
   else
   {
      ...
   }
}

您的代码编译为以下 CIL:

.method public hidebysig static void  Main() cil managed
{
  .entrypoint
  // Code size       21 (0x15)
  .maxstack  2
  .locals init (int32 V_0,
           int32 V_1)
  IL_0000:  nop
  IL_0001:  ldc.i4     0xbb8
  IL_0006:  stloc.0
  IL_0007:  ldc.i4.0
  IL_0008:  stloc.1
  IL_0009:  ldloc.0
  IL_000a:  conv.r8
  IL_000b:  ldloc.1
  IL_000c:  conv.r8
  IL_000d:  div
  IL_000e:  call       void [mscorlib]System.Console::WriteLine(float64)
  IL_0013:  nop
  IL_0014:  ret
} // end of method Example::Main

IL_000d: div 调用是除法运算。这意味着 CLR 将执行这项工作,因此您不会找到任何源代码来执行这项工作。如果我们深入研究浮点值除法运算符的 CLR 源代码(此处显示 coreclr):

TFp FpDiv(TFp dividend, TFp divisor)
{
#ifdef _TARGET_ARMARCH_
    // From the ECMA standard:
    //
    // If [dividend] is zero and [divisor] is zero
    //   the result is NaN.
    // If [dividend] is infinity and [divisor] is infinity
    //   the result is NaN.

    if (dividend == 0 && divisor == 0)
    {
        return TFpTraits::NaN();
    }
    else if (!_finite(dividend) && !_isnan(dividend) && !_finite(divisor) && !_isnan(divisor))
    {
        return TFpTraits::NaN();
    }
#endif // _TARGET_ARMARCH_

    return dividend / divisor;
}

您可以看到它正在处理一些先决条件,然后调用编译器的内部操作。在 x86 上,这又是一个 FDIV 调用,它被记录为引发一个除以零标志,C 运行时,由于 IEEE 754,将变成一个无穷大。这个无穷大的工作方式将链备份到您的 C# 应用程序。