Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Compare two numbers and return -1, 0 or 1

Tags:

Is there a simple math function available that compares numbers x and y and returns -1 when x is less than y, 1 when x is more than y and 0 when they're equal?

If not, would there be a elegant solution (without any if's) to convert the output of Math.Max(x, y) to these returns? I was thinking of dividing the numbers by themselves, e.g. 123/123 = 1 but that will introduce the problem of dividing by 0.

like image 254
Daan Avatar asked Aug 29 '12 18:08

Daan


People also ask

How can I compare two versions?

Open one of the two versions of the document that you want to compare. On the Tools menu, point to Track Changes, and then click Compare Documents. In the Original document list, select the original document. In the Revised document list, browse to the other version of the document, and then click OK.


2 Answers

For your strict -1, 0 or 1 requirement, there's no single method that is guaranteed to do this. However, you can use a combination of Int32.CompareTo and Math.Sign:

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

Alternatively, if you're happy with the normal CompareTo contract which is just stated in terms of negative numbers, positive numbers and 0, you can use CompareTo on its own.

like image 150
Jon Skeet Avatar answered Sep 20 '22 13:09

Jon Skeet


You can do it without using any .NET calls at all and on 1 line. NOTE: Math.Sign and type.CompareTo both use logical if statements and comparison operators which you said you wanted to avoid.

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

as a function

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

Basically, all this does is SHIFT the sign bits all the way to the first position. If the result is unsigned then it will be 0; then it does the same operation and flips the sign bits then ORs them together and the result is wither 1, 0 or -1.

Case where result is -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) 

Case where result is 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) 

Case where result is 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) 

This should also be much faster than using any calls to Math or any other .NET methods.

like image 43
vane Avatar answered Sep 17 '22 13:09

vane