22

是否有一个简单的数学函数可以比较数字 x 和 y,当 x 小于 y 时返回 -1,当 x 大于 y 时返回 1,当它们相等时返回 0?

如果没有,是否有一个优雅的解决方案(没有任何if's)将输出转换Math.Max(x, y)为这些返回?我正在考虑将数字除以它们,例如 123/123 = 1 但这会引入除以 0 的问题。

4

8 回答 8

35

对于您严格的 -1、0 或 1 要求,没有一种方法可以保证做到这一点。但是,您可以使用Int32.CompareTo和的组合Math.Sign

int value = Math.Sign(x.CompareTo(y));

CompareTo或者,如果您对仅以负数、正数和 0 表示的正常合同感到满意,您可以单独使用CompareTo

于 2012-08-29T18:56:50.497 回答
14

您可以在不使用任何 .NET 调用的情况下在 1 行上执行此操作。注意: Math.Sign 和 type.CompareTo 都使用逻辑 if 语句和您说要避免的比较运算符。

int result = (((x - y) >> 0x1F) | (int)((uint)(-(x - y)) >> 0x1F));

作为一个函数

//returns 0 if equal
//returns 1 if x > y
//returns -1 if x < y
public int Compare(int x, int y)
{
    return (((x - y) >> 0x1F) | (int)((uint)(-(x - y)) >> 0x1F));
}

基本上,所有这些都是符号位一直移动到第一个位置。如果结果是无符号的,那么它将是 0;然后它执行相同的操作并翻转符号位,然后将它们OR在一起,结果是 1、0 或 -1。

结果为-1的情况

IS 12 > 15:

12 - 15 = -3            (11111111111111111111111111111101)
-3 >> 0x1F = -1         (11111111111111111111111111111111)

-(12 - 15) = 3          (00000000000000000000000000000011)
3 >> 0x1F = ((uint)0)=0 (00000000000000000000000000000000) cast to uint so 0

    11111111111111111111111111111111
OR
    00000000000000000000000000000000
=   11111111111111111111111111111111 (-1)

结果为 1 的情况

IS 15 > 12:

15 - 12 = 3               (00000000000000000000000000000011)
3 >> 0x1F = 0             (00000000000000000000000000000000)

-(15 - 12) = -3           (11111111111111111111111111111101)
-3 >> 0x1F = ((uint)-1)=1 (00000000000000000000000000000001) cast to uint so 1

    00000000000000000000000000000000
OR
    00000000000000000000000000000001
=   00000000000000000000000000000001 (1)

结果为 0 的情况

IS 15 == 15:

15 - 15 = 0               (00000000000000000000000000000000)
0 >> 0x1F = 0             (00000000000000000000000000000000)

-(15 - 15) = 0            (00000000000000000000000000000000)
0 >> 0x1F = ((uint)0)=0   (00000000000000000000000000000000) cast to uint so 1

    00000000000000000000000000000000
OR
    00000000000000000000000000000000
=   00000000000000000000000000000000 (0)

这也应该比使用任何对 Math 或任何其他 .NET 方法的调用要快得多。

于 2012-08-29T19:59:56.330 回答
6
x.CompareTo(y)

直接来自MSDN

于 2012-08-29T18:54:56.067 回答
3

使用CompareTo()功能

int i = 5;
int n = 6;

int c = i.CompareTo(n);

我通常在if语句中使用它:

int x = 34;
int y = 25;

if(x.CompareTo(y) == 0)
{
  Console.WriteLine("Yes, they are equal");
}
else
{
  Console.WriteLine("No, they are not equal");
}

编辑:

在有人声称 Int32.CompareTo() 可以返回 -1|0|1 以外的值后,我决定自己研究这种可能性。

这是反映的代码Int32.CompareTo()。我看不到除了-1|0|1之外的任何一个都将返回任何东西。

[TargetedPatchingOptOut("Performance critical to inline across NGen image boundaries")]
public int CompareTo(int value)
{
    if (this < value)
    {
        return -1;
    }
    if (this > value)
    {
        return 1;
    }
    return 0;
}


public int CompareTo(object value)
{
    if (value == null)
    {
        return 1;
    }
    if (!(value is int))
    {
        throw new ArgumentException(Environment.GetResourceString("Arg_MustBeInt32"));
    }
    int num = (int) value;
    if (this < num)
    {
        return -1;
    }
    if (this > num)
    {
        return 1;
    }
    return 0;
}
于 2012-08-29T18:54:49.157 回答
1

这是 Math.Sign() 函数。

像这样:

return Math.Sign(x-y);
于 2012-08-29T18:54:30.293 回答
0

您可以尝试使用此代码

var result = a.CompareTo(b);
于 2012-08-29T18:55:42.593 回答
0

对整数使用CompareTo方法:

public int c(int x, int y)
{
  return x.CompareTo(y);
}

void Main()
{       
    Console.WriteLine(c(5,3));
    Console.WriteLine(c(3,3));
    Console.WriteLine(c(1,3));
}
于 2012-08-29T18:57:38.157 回答
0

你试过用compareTo()吗?看这里:http: //msdn.microsoft.com/en-us/library/y2ky8xsk.aspx

于 2012-08-29T19:06:10.897 回答