【问题标题】:Int32.Min vs Int32.MinMagnitudeInt32.Min 与 Int32.MinMagnitude
【发布时间】:2022-11-14 17:56:27
【问题描述】:

.NET 7 中引入的静态方法 Int32.MinInt32.MinMagnitude 有什么区别?他们的签名和描述是一样的:

// 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);

【问题讨论】:

    标签: c# integer numbers .net-7.0


    【解决方案1】:

    MinMagnitude 比较绝对值的输入。因此它几乎等同于:

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

    ...除非比较大小相等但符号不同的数字:

    Debug.Assert(int.MinMagnitude(-1,          1)  == -1);
    Debug.Assert(int.Min( int.Abs(-1), int.Abs(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(-10, -1) == -1);
    Debug.Assert(int.MinMagnitude( -1,  1) == -1);
    Debug.Assert(int.MinMagnitude(  1, -1) == -1);
    

    看看这里的源代码:https://source.dot.net/#System.Private.CoreLib/src/libraries/System.Private.CoreLib/src/System/Int32.cs,892

    【讨论】:

    • 我会争辩为其中一种实现添加source code 可以稍微改善答案=)
    • int.MinMagnitude(-1, 1) 给出-1int.Min(int.Abs(-1), int.Abs(1)) 给出1。所以公式与实际的Int32.MinMagnitude 不等价。
    • int.MinMagnitude(-10, 10)int.MinMagnitude( 10, -10) 会很有趣 =)
    • @TheodorZoulias 几乎是(如果我们想象这样的方法)int.MinByAbs(x, y) =)
    • @TheodorZoulias 它选择具有最小绝对值的数字=)
    【解决方案2】:

    这是新引入的接口INumberBase<TSelf>上的一个方法,是documented as

    比较两个值以计算哪个较小。

    并有备注:

    对于IFloatingPointIeee754<TSelf>,此方法匹配 IEEE 754:2019 minimumMagnitude 函数。这需要将 NaN 输入传播回调用者,并将 -0.0 视为小于 +0.0。

    因此,该评论将证明该方法的文档是错误的,因为它返回的值较小震级,是比较的绝对值。

    因此,如果您想要绝对比较,或者如果您进行浮点数学运算并想要如所述的 NaN 或正/负零比较,则使用 MinMagnitude() 而不是 Min()

    【讨论】:

    • “......如果你做浮点数学......”-- 老实说,我只对MinMinMagnitude 在32 位整数上下文中的区别感兴趣。 AFAIK 浮点数学不适用于整数。
    • 是的,但它是一个适用于所有内置数字类型的接口,并且该句子还有更多部分。
    • 删除我不感兴趣的部分:“因此,如果您想要绝对比较,请使用 MinMagnitude() 而不是 Min()。”-- 老实说,如果我想比较绝对值,我会做int.Abs(x).CompareTo(int.Abs(y));MinMagnitude 整数方法的语义似乎是一团糟。
    【解决方案3】:

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

    此方法返回具有最小绝对值的数字,即幅度(如果相等 - 两个首选的负数)。

    UPD

    我无法访问定义了minimumMagnitude 的IEEE 754 2019,但从the PDF on "The Removal/Demotion of MinNum and MaxNum Operations from IEEE 754™-2018" 开始,原始minNumMag 被定义为:

    minNumMag(x, y)是规范化数字x if | x| &lt; | y|y if | y| &lt; | x|,否则为minNum(x,y)

    正如文档所述 - 删除的原因是 NaN 处理的非关联性,据我所知,在新标准中是“固定的”。

    为此,double 实现可以提供模式细节,我认为:

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

    【讨论】:

    • Int32.MinMagnitude(-2, 2) 返回-2。所以看起来,当相等时,它不是负数。
    • @TheodorZoulias -2 对我来说似乎是负面的。
    • -2对我来说也是负面的,但看起来不像.
    • @TheodorZoulias 在这种情况下,一个是指两者之一,而不是第一。
    • 你想改写它吗?我认为目前这有点令人困惑。
    猜你喜欢
    • 2019-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-26
    • 2011-03-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多