Ternary Operators(Java) - java

I was recently introduced to ternary operators. I managed to make it through a year and a half of CS school without a professor ever mentioning ternary operators. This is my first quarter where my professor is using them regularly. They seem great for shortening code. So, this is a question that will help me understand the bounds of ternary operators and when/how they can be used. Is there a way to shorten the following code block using one long statements using a ternary operator?
if(age < 18){
minors+=1;
} else if(age < 65){
adults+=1;
}else{
seniors+=1;
}

You are updating three unique variables, one way to use ternaries here is something like
minors += (age < 18) ? 1 : 0;
adults += (age >= 18 && age < 65) ? 1 : 0;
seniors += (age >= 65) ? 1 : 0;

You can write it as a single statement:
int dummy = (age < 18) ? (minors += 1)
: (age < 65) ? (adults += 1)
: (seniors += 1);
The value of dummy is unused here. It's just a way to turn the expression into a statement.
Note that I wouldn't consider writing the logic like this in practice. There are multiple side-effects in the code, and that makes it hard to understand.
I think the intent of your current code is very clear as written. Ternary expressions have a tendency to make the code harder to read, in my experience.

The ternary operator is not a good fit for your code because you are changing 3 different variables. I would leave your code as it is.
Suppose, on the other hand, that you had this
if (age < 18) {
number += 1;
} else if (age < 65) {
number = 8;
} else if (age < 90) {
number += 2;
} else {
number = 13;
}
This could be rewritten to look like a kind of switch:
number = age < 18 ? number + 1 :
age < 65 ? 8 :
age < 90 ? number + 2 :
13;
I think this is an improvement on the if version. However, it is not common to nest ternary operators in this way, so you may confuse people looking at your code if you used this version.

Related

Does a simpler representation of this if condition exist?

I used the below conditional statement to ensure that the city name given is of valid length. Length of city should be greater than or equal to 3 and less than or equal to 20.
if(city.length()<3 || city.length()>20) return false;
else return true;
I am told that this conditional statement can be further simplified. Is that right? Then what is the simplified code?
return !(city.length() < 3 || city.length() > 20)
or
return city.length() >= 3 && city.length() <= 20
I simplified your code from IntelliJ IDEA IDE.
Actually it itself suggested to simplify when I used your code there. I recommend you to try IntelliJ IDEA.
return city.length() >= 3 && city.length() <= 20;
If you are already using the IDE, just move the cursor to the code with warning and press ALT+Enter and simplify it.
If city.length() is cheap, then write
return city.length() >= 3 && city.length() <= 20
else you ought to pre-compute city.length() to avoid the potential for two evaluations:
const auto&& /*assuming C++, for Java, you need to use the specific type*/ l = city.length();
return l >= 3 && l <= 20;

How do I detect errors in UPC codes?

I know that UPC codes have a check digit and how to use this check digit to see if the code is valid.
If the code is not valid, my program needs to tell me where the error is. I know it can be done, but how? I need to detect single replacement errors (e.g., typing a 5 in the place of a 2) and transposition errors (e.g., typing 12 instead of 21).
Seems simple but I can't figure it out.
The following code will detect errors in a UPC-A code (12-digit) when considered a String (recommended way).
String upc = "074985003004"; // UPC as a string
int sum = 0;
for(int i = 0; i < a.length(); i++) {
sum += (i%2==0) ? (3*(upc.charAt(i)-48)) : (upc.charAt(i)-48);
}
if (sum % 10 == 0) {
System.out.println("true");
} else {
System.out.println("false");
}
Alternatively, a long can be used in the following code: (Note: the leading zero's must be removed.)
long upc = 74985003004L; // omit leading zeros;
int sum =0;
for(int i=0; i < 12; i++) {
sum += (i%2 == 0) ? (upc % 10) : (sum += 3*(upc % 10));
upc /= 10;
}
if (sum % 10 == 0) {
System.out.println("true");
} else System.out.println("false");
It is usually best to validate the UPC code before testing. i.e. check to make sure it contains the correct number of digits and only the digits 0-9. As mentioned in the link: https://en.wikipedia.org/wiki/Universal_Product_Code, UPC-A detects 100% of single digit errors and 90% of 2-digit transposition errors.
*UPC does not support error correction. However, if you know which digit is incorrect, you can just try all 10 possible values for that digit until no errors are detected (a valid UPC code).

Write a program in java to print the sum of all numbers from 50 to 250(inclusive of 50 and 250) that are multiples of 3 and not divisible by 9

/* when I run this code there is no error in fact output generated is also correct but I want to know what is the logical error in this code? please can any one explain what is the logical error. */
class abc
{
public static void main(String arg[]){
int sum=0;
//for-loop for numbers 50-250
for(int i=50;i<251;i++){
// condition to check if number should be divided by 3 and not divided by 9
if(i%3==0 & i%9!=0){
//individual number which are selected in loop
System.out.println(i);
//adding values of array so that total sum can be calculated
sum=sum+i;
}
}
//final display output for the code
System.out.println("the sum of intergers from 50 to 250 that are multiples of 3 and not divisible by 9 \n"+sum);
}
}
My philosophy is "less code == less bugs":
int sum = IntStream.rangeClosed(50, 250)
.filter(i -> i % 3 == 0)
.filter(i -> i % 9 != 0)
.sum();
One line. Easy to read and understand. No bugs.
Change this:
if(i%3==0 & i%9!=0){
to this:
if(i%3==0 && i%9!=0){
& = bitwise and operator
&& = logical operator
Difference between & and && in Java?
The only problems I saw were:
The variable sum was undeclared
Use && in place of &
int sum = 0;
for (int i = 50; i <= 250; i++) {
if (i % 3 == 0 && i % 9 != 0) {
System.out.println(i);
sum = sum + i;
}
}
System.out.println("the sum of intergers from 50 to 250 that are multiples of 3 and not divisible by 9 \n" + sum);
Well, instead of touching every single value from 50 to 250 like you would do here for(int i=50;i<251;i++), you can consider something like this...
int i = 48;
int sum = 0;
while(i < 250) {
i += 3;
if(i%9 != 0)
sum += i;
}
This is somewhat optimized in the sense that I am skipping over values that I know are not possible candidates.
But, there is a much bigger issue in your code. The following code block prints true, sure. But, it is a bad idea to depend on the & since that is not its job. The & is for bitwise AND whereas the && is for logical AND, which is what you are trying to do.
boolean t = true;
boolean f = false;
System.out.println(f&t);
Why?
In Java, if it is a && operation, as soon as you find the first false, you are sure that the expression will evaluate to false. Meanwhile, in your implementation, it would need to evaluate both sides. f&t will evaluate to false, but the JVM would need to look at both the f and t variables. Meanwhile, on using &&, it wouldn't even need to look at the t.

Beginner Java trouble with Parameters

I am currently learning Java, and have been having problems with parameters. I'm trying to create a program that takes age as input, and classifies the person based on said age.
Younger than 2 is a baby
Younger than 4 is a toddler
Younger than 13 is a child
Younger than 20 is a teenager
Younger than 35 is a young adult
Younger than 65 is middle aged
Younger than 100 is geriatric
100 and older is antique
It needs to return a string classifying the person. I wrote this:
String getMaturityLevel(int age) {
if (age < 2)
return ("a baby");
if (age < 4)
return ("a toddler");
if (age < 13)
return ("a child");
if (age < 20)
return ("a teenager");
if (age < 35)
return ("a young adult");
if (age < 65)
return ("middle aged");
if (age < 100)
return ("geriatric");
if (age >= 100)
return ("antique");
}
Which doesn't compile as it needs a return statement.
So my problem is, how do I effectively write the code? I don't know how to store the results. I tried something different with age < 2.
Any help would be appreciated.
I'm old school, so I believe in only one entry and exit point for a method or function...
The essence of your problem comes down to the compilers inability to guarantee that any one if statement "may" be meet (you and I know that the last one should be, but the compiler won't take that risk).
So instead of having a return for every condition, you could define a single return variable and change it's value based on your needs, for example...
String getMaturityLevel(int age) {
String maturity = "antique";
if(age < 2)
maturity = ("a baby");
else if(age < 4)
maturity = ("a toddler");
else if(age < 13)
maturity = ("a child");
else if(age < 20)
maturity = ("a teenager");
else if(age < 35)
maturity = ("a young adult");
else if(age < 65)
maturity = ("middle aged");
else if(age < 100)
maturity = ("geriatric");
return maturity;
}
Now, in this small piece of code, it may not make much difference, but when you deal with methods that are longer or have multiple compound if/loop statements, a single return statement anywhere in the code can ruin your understanding of what you think the method is doing...it's a nit pick, but anything that makes my life easier ;)
I would also encourage you to use {...} around your if statements, it will stop you from doing something like...
else if(age < 100)
maturity = ("geriatric");
maturity = "Why is the returned value for every condition?";
At the end where
if(age >= 100)
return("antique");
write
else
return("antique");
This is because the compiler thinks there's a possibility there is no return statement if they are all if's(imagine a scenario where everything is false).
Edit: Misread the question.
It appears you strictly have only if statements (no else if statements) therefore at the end of your last if statement, you need to add a return statement:
String getMaturityLevel(int age) {
if(age < 2)
maturity = ("a baby");
if(age < 4)
return("a toddler");
if(age < 13)
return("a child");
if(age < 20)
return("a teenager");
if(age < 35)
return("a young adult");
if(age < 65)
return("middle aged");
if(age < 100)
return("geriatric");
if(age >= 100)
return("antique");
return "no maturity level found";
}
It will only return "no maturity level found" if none of the previous if conditions are true.
Actually, even better, is end it with a return "Error" at the very end without removing anything. This "Error" should never, ever happen, but if it does, you know something went wrong. It's a little bit more robust, I think, and allows you to make the qualification for "antique" (>100) clear still without having to read a single other option.
I recommend using an Enum type (http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html) that would enumerate your maturity levels. Each maturity would have a "value" that would be your string. You could then iterate over your Enum elements and make a single line or two of code... if each element also has a "maturityAge".
public enum MaturityEnum {
BABY (2, "A baby"),
// etc
private int maturityAge;
private String maturityMsg ;
// Accessors etc
}
public int getMaturityLevel(int age) {
for (MaturityEnum maturity : MaturityEnum.getValues()) {
if (maturity.getMaturityAge() > age)
return maturity.getMaturityMsg() ;
// only works if the values of MaturityEnum are in the good order
// to ensure this, you could make a function that gives the list of MaturityEnums
// in the good order :)
}
}
I would definitely change all of the if statements after the first to else if. Also I would recommend putting brackets around each else if / if statement.

Elegant way to code if (10 < x < 20)

Is there an elegant way in Java to code:
if (10 < x < 20) {
...
}
i.e. "if x is between 10 and 20"
rather than having to write
if ((x > 10) && (x < 20)) {
...
}
Thanks!
No. The < operator always compares two items and results in a boolean value, so you cannot chain them "elegantly". You could do this though:
if (10 < x && x < 20)
{
...
}
Kenny nailed it in the comments.
if (10 < x && x < 20)
You want to keep them either both less-than or both greater-than; reversing the direction of the comparison makes for a confusing bit of logic when you're trying to read quickly.
No but you can re-arrange it to make it better, or write a wrapper if it irks you:
if (InRange(x, 10, 20)) { ... }
Or, as Carl says:
if (new Range(10, 20).contains(x)) { ... }
Though personally, I don't see the point. It's a useless abstraction. The bare boolean statement is perfectly obvious.
Though, now that I think about it, and in light of Carl's comment below, there are times when a Range is a perfectly valid and useful abstraction (e.g. when dealing with Feeds). So, depending on the semantics of x, maybe you do want an abstraction.
if(x < 20)
{
if(x > 10)
{
//...
}
}
OR
if(x > 10)
{
if(x < 20)
{
//...
}
}
The only thing you can do is loose the extra parenthesis since the && has a lower precedence than > and <:
if (x > 10 && x < 20) {
...
}
Other than that: there's no shorter way.
The FASTEST way is a switch.
EDIT:
switch(x) {
case 10:
case 11:
case 12:
case 13:
...
case 19: System.out.println("yes");
}
is compiled into a jump table, not a long series of ifs.

Categories

Resources