比较两个数字并返回-1,0或1

Daa*_*aan 17 c#

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

如果没有,是否会有一个优雅的解决方案(没有任何if人)将输出转换Math.Max(x, y)为这些回报?我想把它们自己分开,例如123/123 = 1但这会引入除以0的问题.

Jon*_*eet 30

对于严格的-1,0或1要求,没有一种方法可以保证这样做.但是,你可以使用的组合Int32.CompareToMath.Sign:

int value = Math.Sign(x.CompareTo(y));
Run Code Online (Sandbox Code Playgroud)

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

  • @ChrisGessler:不是随便的 - 但这样做是完全合理的(鉴于文档),我不想*假设它永远不会. (3认同)
  • 我反映了Int32.CompareTo()的代码并且它不会返回除-1 | 0 | 1之外的任何内容,但是,其他一些数字对象可能会像Double或Decimal一样. (2认同)

van*_*ane 12

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

int result = (((x - y) >> 0x1F) | (int)((uint)(-(x - y)) >> 0x1F));
Run Code Online (Sandbox Code Playgroud)

作为一个功能

//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));
}
Run Code Online (Sandbox Code Playgroud)

基本上,这一切确实是SHIFT一路符号位到第一位置.如果结果是无符号的,则它将为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)
Run Code Online (Sandbox Code Playgroud)

结果为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)
Run Code Online (Sandbox Code Playgroud)

结果为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)
Run Code Online (Sandbox Code Playgroud)

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