Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

negation of boolean expressions with XOR

I have this:

// returns true if both are equal (independent of scale) and also checks against null
public static boolean isEqual(BigDecimal val1, BigDecimal val2) {
        // 1. check: both will be null or both will be non-null.
        if (val1 != null ^ val2 != null) return false;
        // 2. check: if not null, then compare if both are equal
        return !(val2 != null && val1.compareTo(val2) != 0);
    }

I want to merge the boolean expressions into one. So I use this:

public static boolean isEqual(BigDecimal val1, BigDecimal val2) {
    return !(val1 != null ^ val2 != null) && !(val2 != null && val1.compareTo(val2) != 0);
}

However, I am worry if this is correct. Is this correct? Could this be simplified/shorten?

With the help of the answer the shorten solution is:

// returns true, if both are null or both are equal 
// (independent of their numbers scales)
public static boolean isEqual(BigDecimal val1, BigDecimal val2) {
    return val1 == null ? val2 == null : val2 != null && val1.compareTo(val2) == 0;
}
like image 370
nimo23 Avatar asked Sep 20 '19 17:09

nimo23


1 Answers

Using ^ as a logical XOR operator is highly unusual. It works, but I would avoid it for readability's sake. != is a good replacement.

return !((val1 != null) != (val2 != null)) && !(val2 != null && val1.compareTo(val2) != 0);

Now you can replace the double negation with ==. Nice.

return ((val1 != null) == (val2 != null)) && !(val2 != null && val1.compareTo(val2) != 0);

You can also distribute the remaining ! via De Morgan's laws:

return ((val1 != null) == (val2 != null)) && (val2 == null || val1.compareTo(val2) == 0);

It's better, but to be honest I still find it unwieldy. I'd go with something more straightforward even if it's not a single line statement:

if (val1 == null) {
    return val2 == null;
}
else {
    return val2 != null && val1.compareTo(val2) == 0;
}

You could use the ternary operator in place of if/else. Up to personal preference which you find more readable:

return val1 == null
    ? val2 == null
    : val2 != null && val1.compareTo(val2) == 0;

You mention that you need to use compareTo(). For others who might read this answer, if you don't have to use compareTo() I'd use equals() instead.

if (val1 == null) {
    return val2 == null;
}
else {
    return val1.equals(val2);
}

Then, as it so happens, you wouldn't even need to write this method at all. The built-in Objects.equals() method does exactly this: it returns true if two objects are equal, or if they're both null.

like image 92
John Kugelman Avatar answered Sep 28 '22 18:09

John Kugelman