Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How we must compare two integers?

Tags:

c

I recently wrote a program that sorts an array. For it, I needed to write a comparison function, which I will pass into it. My comparison function should have returned 1(if x > y), -1(if x < y) or 0(if x = y). I wrote a regular function (Function 1) using conditional expressions, but I was advised to write differently (Function 2). Is it better to write like that? Will a Boolean condition always return 1 for the truth?(I mean if x=0 and y=0 will we always havе (x==y)==1 ?)

Function 1:

int Icmp(void* x, void* y)
{
    int a = *(int*)x;
    int b = *(int*)y;
    if (a > b)
        return 1;
    else if (a < b)
        return -1;
    else
        return 0;
}

Function 2:

int Icmp(void* x, void* y)
{
    return (*(int*)x > * (int*)y) - (*(int*)x < *(int*)y);
}
like image 901
Skiv Hisink Avatar asked Oct 15 '19 04:10

Skiv Hisink


People also ask

How do we compare two integers?

Syntax : public static int compare(int x, int y) Parameter : x : the first int to compare y : the second int to compare Return : This method returns the value zero if (x==y), if (x < y) then it returns a value less than zero and if (x > y) then it returns a value greater than zero. Example :To show working of java.

Can we compare integer with int?

A int is a data type that stores 32 bit signed two's compliment integer. On other hand Integer is a wrapper class which wraps a primitive type int into an object. int helps in storing integer value into memory. Integer helps in converting int into object and to convert an object into int as per requirement.

How do you use a number line to compare two integers?

When comparing two integers on a number line, the integer that is farther to the right is greater. The integer that is farther to the left is less. Compare −6 and −10. Because −6 is farther to the right than −10, it is greater.

What does it mean to compare integers?

Comparing Integers. If there are two numbers we can compare them. One number is either greater than, less than or equal to the other number. If the first number has a higher count than the second number, it is greater than the second number. The symbol ">" is used to mean greater than.


2 Answers

The preferred way to write the non-branching code would be to use a local variable for the operands:

int icmp(const void *x, const void *y)
{
    int a = *(const int *)x;
    int b = *(const int *)y;
    return (a > b) - (a < b);
}

The expression is a common idiom in comparison functions, and if written using variables instead of in-place pointer dereferences it is rather readable too.

The code relies upon the fact that the result of a comparison using >, < or even == is of type int and either 1 or 0. This is required by the C standard - any compiler that generates values like 42 or -1 is by definition not a C compiler.

It is easy to see that max. one of a > b or a < b can be true at a given time, and the result is either 1 - 0, 0 - 1 or 0 - 0.

As to why branchless code - while compilers might generate the exact same code for both functions, they often do not. For example latest GCC and ICC both seem to generate a branch for the first function on x86-64, but branchless code with conditional execution for the latter. And to anyone who says that branches do not matter, then I refer you to the highest-voted QA ever on Stack Overflow.


Is it better to write like that?

I'd say no.

For performance; either it doesn't matter (likely for modern compilers), or it shouldn't be a separate function (and should be built into the code used for sorting), or you shouldn't be sorting at all (e.g. data sorted at creation and not sorted after creation).

For readability (code maintenance, chance of seeing errors in the original version, risk of introducing errors later) I'd prefer your original version; especially when working in a team, and especially when other team members are more familiar with 10 other programming languages that each has very different rules to C.

Specifically; I like this (because casts in actual code make things harder to read):

    int a = *(int*)x;
    int b = *(int*)y;

..and I would rewrite the rest to look like this:

    if (a > b) {
        return 1;
    }
    if (a < b) {
        return -1;
    }
    return 0;
}

..or to look like this:

    if (a > b) return 1;
    if (a < b) return -1;
    return 0;
}

..because else is unnecessary after a return; and because "if without braces followed by statement on its own line" creates a risk of someone accidentally inserting a new line without realizing it and breaking everything (for an example, see https://dwheeler.com/essays/apple-goto-fail.html ).

like image 38
Brendan Avatar answered Sep 24 '22 01:09

Brendan