What is difference between using logical operators using parentheses? - java

I am getting different results: -1 if I use parentheses and 1 if I don't use parentheses.
For test case "30/10/2019" I am getting -1 if I use parentheses and 1 if I don't use parentheses in the following line:
else if((mm==1||mm==3||mm==5||mm==7||mm==8||mm==10||mm==12) && mm<13 && mm>0 && dd>0 && dd<32) return 1;
What is the difference between above line and below line?
else if(mm==1||mm==3||mm==5||mm==7||mm==8||mm==10||mm==12 && mm<13 && mm>0 && dd>0 && dd<32) return 1;
public class Utility {
public static int checkDate(String date){
String []st;
if((date.charAt(2)=='.' && date.charAt(5)=='.')||(date.charAt(2)=='/' && date.charAt(5)=='/')||(date.charAt(2)=='-' && date.charAt(5)=='-'))
{
String token = Character.toString(date.charAt(2));
if(date.charAt(2) == '.') st = date.split("\\.");
else st = date.split(token);
int dd = Integer.parseInt(st[0]);
int mm = Integer.parseInt(st[1]);
int yy = Integer.parseInt(st[2]);
if(mm == 2 && dd>0 && dd<30 && mm<13 && mm>0) return 1;
else if((mm==1||mm==3||mm==5||mm==7||mm==8||mm==10||mm==12) && mm<13 && mm>0 && dd>0 && dd<32) return 1;
else if((mm==4||mm==6||mm==9||mm==11) && dd>0 && dd<31 && mm<13 && mm>0) return 1;
else return -1;
}
else return -1;
}
}
import java.util.Scanner;
public class DateValidation {
public static void main(String[] args) {
// STUDENT CODE BEGINS HERE
Scanner sc = new Scanner(System.in);
String dt=sc.next();
Utility ut = new Utility();
int flag = ut.checkDate(dt);
if(flag==1)
System.out.println("Valid");
else
System.out.println("Invalid");
// STUDENT CODE ENDs HERE
}
}

It will execute the following (in highest order of precedence):
Parentheses ()
Not !
And &&
Or ||
else if((mm==1||mm==3||mm==5||mm==7||mm==8||mm==10||mm==12) && mm<13 && mm>0 && dd>0 && dd<32)
return 1;
It will evaluate (mm==1||mm==3||mm==5||mm==7||mm==8||mm==10||mm==12) first, then && mm<13 && mm>0 && dd>0 && dd<32
else if(mm==1||mm==3||mm==5||mm==7||mm==8||mm==10||mm==12 && mm<13 && mm>0 && dd>0 && dd<32)
return 1;
As for the other, it will evaluate mm<13 && mm>0 && dd>0 && dd<32 first, then mm==1||mm==3||mm==5||mm==7||mm==8||mm==10||mm==12 &&

Parentheses decide the order these booleans are resolved. And binds stronger than Or. In your case you ask for:
mm==12 && mm<13
So left comparison and right comparison must resolve to true. They don't, as you are in month 10. With parenthesis you decide to check if your month value is valid at all, this resolves to true, and then the && check resolves to true as well.

Consider this example.
int a = 5;
System.out.println((a == 5 || a == 10) && a == 8 || a == 9); // false
// evaluates to true && false || false which is false
System.out.println(a == 5 || a == 10 && a == 8 || a == 9); // true
// evaluate to true || false && false && false
// the first true, wins because it is followed by an || so the whole
// expression evaluates to true.
With a && b both both a and b must be true for the statement to be true
With a || b only one of a and b must be true.
This also goes for grouped expressions.
If one expression is true and the other is false, the complete expression is false for && and true for ||. These operators work from left to right so you need to group appropriately, just like arithmetic expressions.
The best advice is always use parentheses to ensure proper evaluation of expressions.

Related

Logic hole with negative numbers in isALeapYear condition in java

public static void main(String[] args){
boolean year = isLeapYear(9999);
System.out.println("Is Leap Year: " + year);
}
public static boolean isLeapYear(int year){
int rem4 = year % 4;
int rem100 = year % 100;
int rem400 = year % 400;
if ((year >= 1 && year <= 9999) && (rem4 == 0) && (rem100 == 0 && rem400 == 0) || (rem100 != 0) && (rem4 == 0)){
return true;
}
return false;
}
When I enter a negative year (so far only -1024) my range condition doesn't work.
But if I enter any other negative leap year it works(-2020). So I don't know what I'm possibly missing, or if the structure of the algorithm is quite right. Any help will be appreciated.
What is expected is that when I enter a year that is not a leap year, and if it is a negative leap year, it returns false.
I know it's considered cool to be concise and all, but this kind of thing is often best done with multiple simple conditionals. Especially when you're first developing it.
if (year < 1 || year > 9999)
return false;
if (rem4 != 0)
return false;
if (rem100 == 0 && rem400 != 0)
return false;
return true;
Or, perhaps:
if (year >= 1 && year <= 9999)
if (rem4 == 0) {
if (rem100 == 0)
return (rem400 == 0);
return true;
}
return false;
Either way will be easier to debug than one big long complicated if statement.
Not exactly sure, but maybe it's because when
|| (rem100 != 0) && (rem4 == 0)) returns a true statement, your whole function returns true, negating the whole first part of your if-statement.
As the || overrides the positive validation part, just add that same validation in the other part of the condition...
(year >= 1 && year <= 9999 && rem4 == 0 && rem100 == 0 && rem400 == 0 || year >= 1 && year <= 9999 && rem100 != 0 && rem4 == 0)

Checking to See which of the three conditions in the If Statement was True in Else If, if one was not?

Assumptions: 1 of 3 of the conditions will be 0.
If I have an if statement defined as follows:
if ((condition1 == 0) || condition2 == 0) || condition3 == 0)) {
do something
}
and 3 following else if statements:
else if (condition1 != 0) {
do something
print which of condition 2 or 3 was 0
}
else if (condition2 != 0) {
do something
print which of condition 1 or 3 was 0
}
else if (condition3 != 0) {
do something
print which of condition 1 or 2 was 0
}
I was thinking perhaps putting nested if statements in the first if statement to see which of the three was 0.
Came up with something. What terrible practice it is to be using this many if statements though. (assume memorizeCondition is stored outside the method of ifs)
if (condition1=0 || condition2 = 0 || condition3 = 0)
if(condition1 = 0)
memorizeCondition = condition1;
if(condition2 = 0)
memorizeCondition = condition2;
if(condition3 = 0)
memorizeCondition = condition3;
else if (condition1 != 0)
memorizeCondition;
calculate condition1;
calculate other condition;
else if (condition2 != 0)
memorizeCondition;
calculate condition2;
calculate other condition;
else if (condition3 != 0)
memorizeCondition;
calculate condition2;
calculate other condition;
what about this:
if ((condition1 == 0) || condition2 == 0) || condition3 == 0)) {
do something
} else {
if (condition1 != 0) {
do something
print which of condition 2 or 3 was 0
}
if (condition2 != 0) {
do something
print which of condition 1 or 3 was 0
}
if (condition3 != 0) {
do something
print which of condition 1 or 2 was 0
}
}
If there are a lot more than 3 conditions you can add them to a collection and then use stream.filter() to remove all non matching conditions.

java.lang.StringIndexOutOfBoundsException: String index out of range: -1 (Works with another program)

I'm supposed to create a program that finds the longest palindrome in a DNA string. Unlike a regular palindrome program, this one requires A to match with T and C to match with G (so instead of 1221 we'd have TCGA for example). After trying myself I did find a very good program for the normal palindrome problem, the one on this website:
http://www.journaldev.com/530/java-program-to-find-out-longest-palindrome-in-a-string
I then tried to modify it to fit my needs. Basically the changes I made were the following:
Instead of those strings shown in the example, I read a string from the argument line. The string is the following DNA sequence (although I tested the program with only parts of it):
http://introcs.cs.princeton.edu/java/31datatype/genomeVirus.txt
Instead of the command
while (left >= 0 && right < s.length()
&& s.charAt(left) == s.charAt(right)) {
left--;
right++;
}
I did:
while (left >= 0 && right < s.length()
&& s.charAt(left) == 'A' && s.charAt(right) == 'T' || s.charAt(left) == 'T' && s.charAt(right) == 'A'
|| s.charAt(left) == 'G' && s.charAt(right) == 'C' || s.charAt(left) == 'C' && s.charAt(right) == 'G')
{
left--;
right++;
(Full code below)
However, when I try this program on a string, I always get the error:
java.lang.StringIndexOutOfBoundsException: String index out of range: -1
at java.lang.String.substring(Unknown Source)
at LongestPalindrome.intermediatePalindrome(LongestPalindrome.java:17)
at LongestPalindrome.longestPalindromeString(LongestPalindrome.java:26)
at LongestPalindrome.main(LongestPalindrome.java:5)
I just don't get it! I don't realize how I'm getting out of the string, when I try the original program I linked to, it always works with no matter which string. I feel like I'm doing everything correctly, simply replacing the == command with various scenarios that should make sense.
I figured it might have something to do with
return s.substring(left+1, right);"
I tried to take the +1 away but it seems to ruin the whole deal. I just don't realize how I'm going out of the string, since it worked perfectly before my adjustments.
Any help would be greatly appreciated! Below is the code!
public class LongestPalindrome {
public static void main(String[] args) {
String gen = new String(args[0]);
System.out.println(longestPalindromeString(gen));
}
static public String intermediatePalindrome(String s, int left, int right) {
if (left > right) return null;
while (left >= 0 && right < s.length()
&& s.charAt(left) == 'A' && s.charAt(right) == 'T' || s.charAt(left) == 'T' && s.charAt(right) == 'A'
|| s.charAt(left) == 'G' && s.charAt(right) == 'C' || s.charAt(left) == 'C' && s.charAt(right) == 'G')
{
left--;
right++;
}
return s.substring(left+1, right);
}
// O(n^2)
public static String longestPalindromeString(String s) {
if (s == null) return null;
String longest = s.substring(0, 1);
for (int i = 0; i < s.length() - 1; i++) {
//odd cases like 121
String palindrome = intermediatePalindrome(s, i, i);
if (palindrome.length() > longest.length()) {
longest = palindrome;
}
//even cases like 1221
palindrome = intermediatePalindrome(s, i, i + 1);
if (palindrome.length() > longest.length()) {
longest = palindrome;
}
}
return longest;
}
}
You are calling it with right == 0. You need to change the first call to:
String palindrome = intermediatePalindrome(s, i, i+1)
Operator precedence problem. You've added some || conditions which are also evaluated even if the range checks fail. It should be:
while (left >= 0 && right < s.length()
&& (s.charAt(left) == 'A' && s.charAt(right) == 'T'
|| s.charAt(left) == 'T' && s.charAt(right) == 'A'
|| s.charAt(left) == 'G' && s.charAt(right) == 'C'
|| s.charAt(left) == 'C' && s.charAt(right) == 'G'))
Note the parentheses around the entire second operand of the second &&.

Simple logic not working or am I missing something?

I don't understand why the following class prints out:
true
false
I thought the output should be:
false
false
because this line prints false:
System.out.println((11 >= 1 || 11 <= 10) & (true == false));
so this line should also print false:
System.out.println(in1To10(11, false));
What am I missing here? Here's the class.
public class TestClass {
public static void main(String[] args) {
System.out.println(in1To10(11, false));
System.out.println((11 >= 1 || 11 <= 10) & (true == false));
}
public static boolean in1To10(int n, boolean outsideMode) {
if ((n >= 1 || n <= 10) & (outsideMode == false)) {
return true;
}
return false;
}
}
You want to test if value is in the range 1 to 10 ?
If thats the case, change (n >= 1 || n <= 10) to (n >= 1 && n <= 10)
( true )
( true ) & ( true )
(true || false ) & ( true ) <--- false == false is true!
if ((n >= 1 || n <= 10) & (outsideMode == false)) {
return true;
}
Look, is n >= 1? Yes, so it's true. true v p <-> true, so Java doesn't even check further. true /\ true <-> true so we enter if. return true;
Your code is in plain English:
if ((n is greater or equal to 1 OR smaller or equal 10) AND is the mode set to false)
return true
If you want it to return true if the number is between 1 and 10 incl, it would be:
if ((n is greater or equal to 1 AND smaller or equal 10) AND is the mode set to false)
return true
which in Java is:
if ((n >= 1 && n <= 10) && (outsideMode == false)) {
return true;
}
Also remember to use && and || as they are logical operators instead of | and & bitwise logical operators when dealing with boolean values.
so this line should also print false: System.out.println(in1To10(11, false));
No, this line should not print false. Although the first parameter, 11, indeed turns the expression n >= 1 || n <= 10 from your method into 11 >= 1 || 11 <= 10, which matches your other expression, the second parameter, false, turns outsideMode == false into false == false, while your other expression has true == false.
That is why the two outputs are different: the output from in1To10 is true because the comparison false == false produces true, while the output from main is false, because true == false produces false.
Note: your expression does not match its stated goal of checking if n is between 1 and 10, inclusive. You need to replace || with && to accomplish that.
I think you missed that in function in1to10, you are comparing (false == false) and in main you are comparing (true == false). And so is the result. Hope this helps.
Let's decompose the test in in1to10 :
Parameters : outsideMode = false; n = 11;
(n >= 1 || n <= 10) :=> (11 >= 1 || 11 <= 10) :=> (true || false) :=> so TRUE
outsideMode == false :=> false == false :=> so TRUE
In the end :
public static boolean in1To10(int n, boolean outsideMode) {
if ((TRUE) & (TRUE)) {
return true;
}
return false;
}
:=> return TRUE !
This will return true. How?
if ((n >= 1 || n <= 10) & (outsideMode == false)) {
return true;
}
You are passing 11 and false to the function.
When it goes to inside the first condition it will check that n >= 1 mean 11 >= 1 that is true, so it will not check n<=10. Again it will check the second condition and your outsideMode is false,
That will be like this, (true) & (true)
hence the whole condition will be true and the funciton will return true.
Again the second condition,
(11 >= 1 || 11 <= 10) & (true == false)
It will return false. How?
As 11 >= 1 is true and again it will not check 11 <= 10, and right side is false.
So the condition will be become like this,
true & false that will be false.

operator precedence && and ||

please ignore the question - its wrong
I am not sure if my question is issue is related to operator precedence- Just to rule out that I added additional bracket. My understanding is in that case that code in each bracket will be executed. So basically all the OR operation will happen and its output would be AND'ed to condition a.
I have below set of parameters a = true and c = 254 , b is not availble ( b is initialized to 0 -At any given time either b or c only is availble) . So for the above condition I am expecting if condition to result in true but it's resulting in false condition. Any reason why ? Also what is best way to debug such things as in where exactly condition is going wrong - any pointers
if ((a == true) && ((b == 460) || (b == 454) || (b == 455) ||
(c> 13568 && c< 14335) ||
(c> 10640 && c< 10655) ||
(c> 11296 && c< 11311) ||
(c> 25600 && c< 26111) || (c== 7825)))
First a is evaluated, if (a == true) evaluated to true, then only it will execute next && statement
((b == 460) || (b == 454) || (b == 455) ||
(c> 13568 && c< 14335) ||
(c> 10640 && c< 10655) ||
(c> 11296 && c< 11311) ||
(c> 25600 && c< 26111) || (c== 7825))
Inside this, it will check for any one condition which is true, and once it encounter any one statement true, it return from there.
For your condition to be true, a must be true, and in addition, at least one of the conditions on b or c must be true.
Therefore, if a==true and c==254, you will get false, since c is not within any of the ranges you allow, and, as you said, b is not available (which I'm assuming means it doesn't have one of the 3 values you allow).
It would be much simpler if the code is written in a more readable manner;
bool isEqualToAny(int valueToCheck, int[] listToCheckIn){
boolean isMatch = false;
(for item in listToCheckIn){
if (item == valueToCheck){
isMatch = true;
break;
}
}
}
bool isWithinRange(int valueToCheck, int min, int max){
return (valueToCheck > min && valueToCheck < max);
}
if ((a == true)
&& (isEqualToAny(b, int[]{460,454,455})
|| isWithinRange(c,3568,14335)
|| isWithinRange(c,10640,10655)
|| isWithinRange(c,11296,11311)
|| isWithinRange(c,25600,26111)
|| isWithinRange(c,10640,10655)
|| (c== 7825)))
In java8 you can use an array of Tuples to make #isWithinRange more like #isEqualToAny

Categories

Resources