Home > Net >  Int32.Min vs Int32.MinMagnitude
Int32.Min vs Int32.MinMagnitude

Time:11-14

What is the difference between the static methods Int32.Min and Int32.MinMagnitude, that were introduced in .NET 7? Their signature and description is the same:

// Compares two values to compute which is lesser.
public static int Min (int x, int y);

// Compares two values to compute which is lesser.
public static int MinMagnitude (int x, int y);

CodePudding user response:

MinMagnitude compares the absolute values of the inputs. Hence it is almost equivalent to:

int.MinMagnitude(x, y) = int.Min(int.Abs(x), int.Abs(y))

...except when comparing numbers of equal magnitude, but different sign:

Debug.Assert(int.MinMagnitude(-1,          1)  == -1);
Debug.Assert(int.Min( int.Abs(-1), int.Abs(1)) ==  1);

Some examples:

Debug.Assert(int.MinMagnitude( 10,  1) ==  1);
Debug.Assert(int.MinMagnitude(-10,  1) ==  1);
Debug.Assert(int.MinMagnitude( 10, -1) == -1);
Debug.Assert(int.MinMagnitude(-10, -1) == -1);
Debug.Assert(int.MinMagnitude( -1,  1) == -1);
Debug.Assert(int.MinMagnitude(  1, -1) == -1);

Have a look at the source code here: https://source.dot.net/#System.Private.CoreLib/src/libraries/System.Private.CoreLib/src/System/Int32.cs,892

CodePudding user response:

Based on the implementation for Int32:

  public static int MinMagnitude(int x, int y)
  {
        int absX = x;

        if (absX < 0)
        {
            absX = -absX;

            if (absX < 0)
            {
                return y;
            }
        }

        int absY = y;

        if (absY < 0)
        {
            absY = -absY;

            if (absY < 0)
            {
                return x;
            }
        }

        if (absX < absY)
        {
            return x;
        } 
        if (absX == absY)
        {
            return IsNegative(x) ? x : y;
        }
        return y;
  }

This method returns number with minimal absolute value, i.e. magnitude (if equal - the negative of the two preferred).

UPD

I can't get access to IEEE 754 2019 where minimumMagnitude is defined, but from the PDF on "The Removal/Demotion of MinNum and MaxNum Operations from IEEE 754™-2018", the original minNumMag was defined as:

minNumMag(x, y) is the canonicalized number x if | x| < | y|, y if | y| < | x|, otherwise minNum(x,y).

As the doc states - reason for removal was non-associativity for NaN handling which, I understand is "fixed" in the new standard.

For this the double implementation can give mode detail, I think:

public static double MinMagnitude(double x, double y)
{
    // This matches the IEEE 754:2019 `minimumMagnitude` function
    //
    // It propagates NaN inputs back to the caller and
    // otherwise returns the input with a lesser magnitude.
    // It treats  0 as lesser than -0 as per the specification.
 
    double ax = Abs(x);
    double ay = Abs(y);
 
    if ((ax < ay) || double.IsNaN(ax))
    {
        return x;
    }
 
    if (ax == ay)
    {
        return double.IsNegative(x) ? x : y;
    }
 
    return y;
}

CodePudding user response:

It's a method on the newly-introduced interface INumberBase<TSelf>, and is documented as:

Compares two values to compute which is lesser.

And has the remark:

For IFloatingPointIeee754<TSelf> this method matches the IEEE 754:2019 minimumMagnitude function. This requires NaN inputs to be propagated back to the caller and for -0.0 to be treated as less than 0.0.

So that remark would proves the documentation of the method to be wrong, as it returns the value with the lesser magnitude, being the compared absolute values.

So if you want absolute comparisons, or if you do floating point math and want NaN or positive/negative zero comparisons as described, then use MinMagnitude() instead of Min().

  • Related