简体   繁体   中英

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

Question

I would like to see the piece of code that does a floating-point division and returns Infinity when dividing by zero. Where can I find it?

Code example

The motivation of wanting to know that comes from this code taken from the .NET documentation. I would have expected to get a DivideByZeroException but instead I get 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

Documentation

I found the documentation stating that floating-point division by zero does not throw an exception, so that's fine:

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.

Code in .NET Framework

In Visual Studio, I hovered over the "/" division sign and Resharper shows

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

And now, I'd like to see the implementation of that to see how that Infinity is returned. But I can't find it.

I checked here

but don't see the division operator.

The above link then lead me here

but also nothing about the implementation detail.

I also looked here

but only see commented out code

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

Also nothing in the Double implementation of corefx :

I would have expected something liked this (pseudo code):

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

Your code compiles down to the following 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

That IL_000d: div call is the divide operation happening. This means the CLR will perform the work, so you won't find any source code doing the work. If we dig into the CLR source code (here showing the coreclr) for the divide operator for floating point values:

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;
}

You can see it's handling some preconditions, then calling into the compiler's intrinsic operation. On x86 that will in turn be a FDIV call, which is documented as raising a divide by zero flag, which the C runtime, thanks to IEEE 754, will turn into an infinity. This infinity works it way back up the chain to your C# app.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM