Java learning road 06 - logical structure trap

Keywords: Java Back-end

Architecture diagram

suspension

If only one logical judgment statement is connected, this statement will be connected with the nearest logical judgment statement, such as system. Out. Println ("none zero!") in the following example; Will be connected under the if structure, which is called suspension

while(iter < 10)
	if(iter != 0)
		System.out.println("none-zero!");

Errors often occur when the logic expressed by the indentation does not match the actual program execution logic

For example, in the following equation, when a is not greater than 1, the developer wants to assign b to 20, but the suspension feature of else statement is actually connected to the nearest logical judgment statement if (a > 1), so b will be assigned to 20 only when a is greater than 5. Indentation has no impact on the execution of the program

int a = -1;
int b = 0;

if(a > 1)
	if(a > 5)
		b = 1;
else
	b = 10;

System.out.println("b = " + b);

Importance of braces

In fact, braces can be omitted when there is only one statement in the logical judgment. If the statement is also a logical judgment statement, the principle can continue to apply

For example, the following program. However, for the sake of readability, avoid nesting too many unnecessary logical structures

int a = 5;

if(a > 0)
	if(a > 1)
		if(a > 2)
			if(a > 3)
				if(a > 4)
					System.out.println("hi");

If we add an else statement under each logical judgment and change the value of a, who is it actually hanging under?

Because the statements under logical judgment can be interpreted as if(...) {}, we can see that the nested if statements in the program example can actually be regarded as only one statement if(...){if(...) {...}}

The judgment of else statement is still allocated to the nearest logical judgment formula according to the characteristics of suspension. If the logical judgment formula has been allocated, else statement will be allocated like the previous layer

The following program types are commonly known as "wave fist" (see its shape). When actually writing programs, we should think about how to reduce the nesting level

int a = 11;

if(a > 0)
	if(a > 10)
		if(a > 20)
			if(a > 30)
				if(a > 40)
					System.out.println("hi");
				else
					System.out.println("40");
			else
				System.out.println("0");
		else
			System.out.println("20");
	else
		System.out.println("10");
else
	System.out.println("0");

Let's convert the above program into pseudo code. In fact, the following else statement can be imagined as a queue waiting for the queue crowd assigned to the above if statement

/*Treat as a single statement*/
if(...) // A
	if(...) // B 
		if(...) // C
			if(...) // D
				if(...) // E
					// do something
else // Assigned to E
	System.out.println("...");
else // Assigned to D
	System.out.println("...");
else // Assigned to C
	System.out.println("...");
else // Assigned to B
	System.out.println("...");
else // Assigned to A
	System.out.println("...");

Therefore, the actual output results are:

20

If the developer does formatting such as indentation at the beginning of the design, the logical judgment of the program is easy to handle, otherwise it's really terrible... But anyway, try to add braces when writing the program, whether there is only one statement or not

Adding parentheses can make it easier for subsequent developers to understand the program logic and avoid program errors. For example, the following programs actually have two problems

  1. If (a > 5) can only hang one statement, that is, Sytem.out.println("a is greater than 5"); It will be executed anyway
  2. else statement must hang after if statement, but Sytem.out.println("a is greater than 5"); An error occurred because it does not belong to an IF statement
int a = 4;
if(a > 5)
	Sytem.out.println("a Greater than 0");
	Sytem.out.println("a Greater than 5");
else
	Sytem.out.println("a Not more than 5");

Safer approach → it won't take you much valuable time (cherish the time of subsequent developers to debug) 🙏)

int a = 4;
if(a > 5){
	Sytem.out.println("a Greater than 0");
	Sytem.out.println("a Greater than 5");
}
else{
	Sytem.out.println("a Not more than 5");
}

The compiler will treat the contents in braces as a statement, which is equivalent to hanging a statement under logical judgment, so let's take another example. The following two program structures are actually the same

for (int i=0; i<5; i++){
	for (int j=0; j<5; j++){
		for (int k=0; k<5; k++){
			// do something
        }
  	}
}
for(int i=0; i<5; i++)
	for(int j=0; j<5; j++)
		for(int k=0; k<5; k++){
			// do something
		}

null statement

When a semicolon is added directly to the end of a logical judgment statement, a so-called null statement is generated, that is, the logical judgment statement you write does nothing, and its function is the same as that of the curly braces added above

If the while statement encounters a null statement, it will encounter infinite loops. Similarly, if the for loop does not have a good exit mechanism, it is easy to get stuck in the infinite loop

For example, the following statements actually have null statement s, and only if statements can exit safely

if(i == 3);

while(iter != myobj.gain());
	System.out.println("I'm here!");;

for(i=0;;i++);

Integer and brin

C/C + + does not have the so-called true Boolean value, so it uses non-0 and 0 instead. Therefore, we often see that integers are used as the basis for true or false in logical judgment statements

However, in java, boolean type cannot operate with other types. Therefore, statements such as if, while, do while, and for need to avoid mixed integer and Boolean judgment

For example, the following error program code

public static void main(String[] args){
	int a=10, b=15, c=20, d=25;
	
	if(a>b && b>c){
		System.out.println("1. Successful execution");
	}
	else if((++d >= a--) == 1){ // boolean cannot be compared with an integer
		System.out.println("2. Successful execution");
	}
	else{
		System.out.println(3. Successful execution);
	}
}

Use floating point for judgment

When actually writing programs, try not to use floating-point numbers for judgment. Although the following programs can run smoothly, the actual printed value is not equal to the judgment value, because there will be more or less errors in the operation and assignment of floating-point numbers. Try to use integer or other variable types as the basis for judgment

public class MathDemo {

	public static void main(String[] args) {
		float c=123456789.123456789f;
		if(c > 123456789.123456789f){
			System.out.println("c > 123456789.123456789");
		}
		else if(c == 123456789.123456789f){// DANGER
			System.out.println("c == 123456789.123456789");
		}
		else{
			System.out.println("c < 123456789.123456789");
		}
		
		System.out.println(c);
	}
}

Data type judgment principle

Data types available for comparison

  1. int
  2. long
  3. double
  4. float
  5. char
  6. String

In principle, as long as it can pass through Automatic type conversion The matching variable types can be compared with each other. However, generally, they are compared between the same data types

int 		i = 6;
long 		l = 18l;
double 		d = 6.0d;
float 		f = 6.0f;
char 		ch = 'a';
String 		s = "a";
boolean 	b = true;

/*Comparison between integers*/
System.out.println(i > l); // false

/*Comparison between floating point numbers*/
System.out.println(f == d); // true

/*Comparison between integers and floating point numbers*/
System.out.println(i == d); // true
System.out.println(l > f); // true

/*Between integer and character*/
System.out.println(i > ch); // false
System.out.println(l > ch); // false

/*Integers, floating point numbers, and characters cannot be compared with strings*/
System.out.println(i > s);
System.out.println(d > s);
System.out.println(ch == l);

/*Boolean type cannot be compared with any type*/
System.out.println(i > b);
System.out.println(l > b);
System.out.println(f > b);
System.out.println(d > b);
System.out.println(ch > b);
System.out.println(s > b);

case down problem

If the break statement is not filled in the case of the switch statement, the Execution Authority will automatically execute another case downward until a break is encountered

For example, in the following switch case, after annotating all break s, all expressions below the current case will be executed

int a = 100;

switch(a/10){
	case 10:
	case 9:
		System.out.println("A");
		// break;
	case 8:
	case 7:
		System.out.println("B");
		// break;
	case 6:
		System.out.println("C");
		// break;
		
	default:
		System.out.println("fail,");
		// break;
}

Output results:

A
B
C
 fail,

When the program executes output at the same time under multiple different conditions, you may wish to check whether the case of the stwich statement is correctly filled in the break statement

Output type of switch

The values of expressions after JDK7.0 can be basic data types byte, short, int, char, and String, but the data type in the switch judgment must be consistent with the variable type after case, otherwise an exception will be thrown during program execution

The variable type of the expression after switch cannot be long, float, double or Boolean. Remember the precision of floating point numbers, so it is not suitable for judgment in switch statements. Brin has a better understanding of the problem that can be solved with if without using switch structure

As for long, it is quite special. See whether the long type will be added in the subsequent java updates. It is not supported at present

Scanner s = new Scanner(System.in);
System.out.print("Input string str: ");

String str = s.next();

switch(str){
	case "apple":
		System.out.println("Apple");
		break;
	case "banana":
		System.out.println("Banana");
		break;
	case "watermelon":
		System.out.println("watermelon");
		break;
	case "papaya":
		System.out.println("Papaya");
		break;
	default:
		System.out.println("There is no such fruit");
		break;
}

Expression for

Let's first look at the order in which the for statement is executed. Take the following code as an example

First, int n=1 is an initialization statement to assign a value to the local variable n (or other declared variables). This statement will be executed only once

Next, judge whether the variable meets the condition n < 5. If it is true, enter the loop

After completing the statement in the loop, the local variable n will be incremented by N + +, and then judge whether it meets n < 5. If it is true, enter the loop again, otherwise exit the for loop. The subsequent loop processing is the part of the loop

for(int n=1; n<5; n++){
	// do something
}

As like as two peas, we can see that the expression logic of for is presented in while way, which is believed to be better understood. As seen in the following pseudo code, the functions of the two logical judgments are exactly the same.

for(int i=100; (i%5 == 0)&(i > 8); i=i-8){
	System.out.println("i = " + i);	
}
int i = 100;
while((i%5 == 0)&(i > 8)){
	System.out.println("i = " + i);	
	i -= 8;
}

The output results are:

i = 100

Omit expression

The three judgements of the for loop can be omitted, and the default is true after the second one is omitted

For example, omitting the first expression is equivalent to removing the initialization function. If you want the program to run normally, you need to initialize the variables

int i = 0;
for(; i<5; i++){
	System.out.println("hi");
}

Omitting the second judgment is equivalent to omitting the condition for leaving the for loop, so that the first semicolon is always true, which will make the program unable to jump out of the loop

If you do not want the program to become an infinite loop, you can write a conditional statement to execute the jump in the loop

int a = 0;
for(int i=0;;i++){
	if(i>10)
		break;
	a++;
}

System.out.println("a = " + a);

Omitting the third expression is equivalent to removing the variable operation that will be performed later in the loop. This expression will submit the operation result to the second judgment expression to arbitrate whether to enter the loop again

Omitting this item may also cause infinite loop, because the judgment variable has not changed since initialization, so an expression must be added to the loop body to execute correctly

for(int i=0; i<50;){
	if(i%2 == 0){
		System.out.println("even!");
		i += 7;
	}
}

Omit three expressions, which are expressed as an infinite loop, which is equivalent to a while(1) loop

for(;;){}

while(1){}

Fill in multiple judgements in for

In addition to the second judgment, the first and third judgment can be extended

For example, the following program initializes i and j at the same time and performs operation on these two variables, but there will only be j < Q for exit loop condition, which cannot be extended

int i, j;
int p = 0, q = 8;
for(i = 0, j = 0; j < q; --i, j++){
	System.out.println("i = " + i + ", j = " + j);
}

Output results:

i = 0, j = 0
i = -1, j = 1
i = -2, j = 2
i = -3, j = 3
i = -4, j = 4
i = -5, j = 5
i = -6, j = 6
i = -7, j = 7

Interested friends can use the extended function of for loop to write some code. For example, the following code refers to printing a 99 multiplication table using a for loop loop

But remember not to do this when actually writing programs Hey 😎

for(int i=1, j=1; j<10; i=(i==9 ? (++j/j) : i+1)){
	System.out.print(i + " * " + j + " = " + i*j + (i==9 ? '\n' : ", "));
}

Output results:

1 * 1 = 1, 2 * 1 = 2, 3 * 1 = 3, 4 * 1 = 4, 5 * 1 = 5, 6 * 1 = 6, 7 * 1 = 7, 8 * 1 = 8, 9 * 1 = 9
1 * 2 = 2, 2 * 2 = 4, 3 * 2 = 6, 4 * 2 = 8, 5 * 2 = 10, 6 * 2 = 12, 7 * 2 = 14, 8 * 2 = 16, 9 * 2 = 18
1 * 3 = 3, 2 * 3 = 6, 3 * 3 = 9, 4 * 3 = 12, 5 * 3 = 15, 6 * 3 = 18, 7 * 3 = 21, 8 * 3 = 24, 9 * 3 = 27
1 * 4 = 4, 2 * 4 = 8, 3 * 4 = 12, 4 * 4 = 16, 5 * 4 = 20, 6 * 4 = 24, 7 * 4 = 28, 8 * 4 = 32, 9 * 4 = 36
1 * 5 = 5, 2 * 5 = 10, 3 * 5 = 15, 4 * 5 = 20, 5 * 5 = 25, 6 * 5 = 30, 7 * 5 = 35, 8 * 5 = 40, 9 * 5 = 45
1 * 6 = 6, 2 * 6 = 12, 3 * 6 = 18, 4 * 6 = 24, 5 * 6 = 30, 6 * 6 = 36, 7 * 6 = 42, 8 * 6 = 48, 9 * 6 = 54
1 * 7 = 7, 2 * 7 = 14, 3 * 7 = 21, 4 * 7 = 28, 5 * 7 = 35, 6 * 7 = 42, 7 * 7 = 49, 8 * 7 = 56, 9 * 7 = 63
1 * 8 = 8, 2 * 8 = 16, 3 * 8 = 24, 4 * 8 = 32, 5 * 8 = 40, 6 * 8 = 48, 7 * 8 = 56, 8 * 8 = 64, 9 * 8 = 72
1 * 9 = 9, 2 * 9 = 18, 3 * 9 = 27, 4 * 9 = 36, 5 * 9 = 45, 6 * 9 = 54, 7 * 9 = 63, 8 * 9 = 72, 9 * 9 = 81

The problem of while(i == i+1)

Please think about such a problem. How much should i be assigned to make the following while loop become infinite loop

while(i == i + 1){}

This problem is bound to involve the question of what variables will be equal to themselves after adding 1 in java official document Gives a very clear answer

The (positive and negative) infinite value or a very large value of a floating-point number is still equal to itself after addition and subtraction with a finite value or an infinite value equal to its own sign

Therefore, we set the floating-point number to positive and negative infinity, and found that we can set the while() judgment to infinite loop

float i = Float.POSITIVE_INFINITY; // Positive infinity
// float i = Float.NEGATIVE_INFINITY; //  Negative infinity
// double i = Double.POSITIVE_INFINITY; // double type can also be used

while(i == i + 1){}

In addition, the accuracy of floating-point numbers has a minimum limit, that is, when floating-point variables are assigned a very large value, addition and subtraction will not affect the original value

For example, adding 1 to the minimum value of float is actually equal to itself

float i = -Float.MAX_VALUE;

while(i == i + 1){}

Or manually assign a very large positive and negative constant to get the same effect

float i = 9999999999999f;

while(i == i + 1){}

For the minimum value of floating point numbers, refer to the previous article

Posted by rgermain on Sat, 04 Dec 2021 12:16:41 -0800