簡體   English   中英

對 C# 進行浮點除法的代碼在哪里?

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

問題

我想看看執行浮點除法並在除以零時返回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

將浮點值除以零不會引發異常; 根據 IEEE 754 算術規則,它會導致正無窮大、負無窮大或非數字 (NaN)。 由於以下示例使用浮點除法而不是 integer 除法,因此該操作不會引發 DivideByZeroException 異常。

.NET 框架中的代碼

在 Visual Studio 中,我將鼠標懸停在“/”除號上,Resharper 顯示

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

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

我在這里檢查

但看不到除法運算符。

然后上面的鏈接將我帶到這里

但也沒有關於實現細節。

我也看過這里

但只看到注釋掉的代碼

///        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調用,這被記錄為引發除以零標志,由於 IEEE 754,C 運行時將變成無窮大。 這種無窮大的工作方式將鏈備份到您的 C# 應用程序。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM