My code is supposed to convert scores to letter grades, so I used if statements. Just wondering if there's a way to use a switch statement instead of if-statements. I have no idea how to convert it. Also, is one better than the other?
public static void determineGrade(int numArray[], char letterArray[]) {
int scoreCount = numArray.length;
for (int i=0; i < scoreCount; i++) {
if (numArray[i] >= 90 && numArray[i] <=100) {
letterArray[i] = 'A';
}
if (numArray[i] >= 80 && numArray[i] < 90) {
letterArray[i] = 'B';
}
if (numArray[i] >= 70 && numArray[i] < 80) {
letterArray[i] = 'C';
}
if (numArray[i] >= 60 && numArray[i] < 70) {
letterArray[i] = 'D';
}
if (numArray[i] >= 0 && numArray[i] < 60) {
letterArray[i] = 'F';
}
}
displayTestScores(numArray, letterArray);
public char getGrade(int input){
switch(input/10)
{
case 9: return 'A';
case 8: return 'B';
case 7: return 'C';
case 6: return 'D';
default: return 'F';
}
}
Then
for (int i=0; i < scoreCount; i++) {
letterArray[i] = getGrade(numArray[i]);
}
You can switch statement in this case but I wouldn't recommend due to the fact you will have way too many cases. You will use at least 100 cases to input because of your if statement conditions.
case 100 ://code
break;
case 50 ://skip a bit
case 0 :
There is way too many cases and a waste of time and lines.
Your conditions are ranges. Java switch statements have cases for values, not ranges.
Since you have a limited number of cases, you could list each one of them independently. However, this would make your code much longer, with 100 cases.
And there's also some math trickery you could do to find the lower number divisible by 10, and switch on that. But the if statement is simpler to implement and read.
All that said, your second expression in the if statements is unnecessary, if you use an else statement, not an independent if. And you want to use an else, because it would be silly to continue checking all the remaining cases after the first one whose condition is met.
if (numArray[i] >= 90 ) { // Can you have values > 100?
letterArray[i] = 'A';
}
else if (numArray[i] >= 80 ) { // If we're checking this, we know numArray[i] < 90
letterArray[i] = 'B';
}
else if ...
You're looking to produce a switch statement that has cases based on ranges. It's not really what switch statements are meant for. the if route is more elegant/a better solution for your case imo.
In Java,Using switch statement with a range of value in each case?
Related
I am trying to create some code to read roman numerals and turn them into an integer. the issue im having is the 9s and 4s. I am able to get it to read if the 9 or 4 is inside a number (I.E LIV is 54 and LXI is 59) but by its self (IV and IX) it only reads 6 and 11.
here is my code:
public static void RomantoInt(String s) {
HashMap<Character, Integer> RomanNums = new HashMap<>();
int count = 0;
RomanNums.put('I', 1);
RomanNums.put('V', 5);
RomanNums.put('X', 10);
RomanNums.put('L', 50);
RomanNums.put('C', 100);
RomanNums.put('D', 500);
RomanNums.put('M', 1000);
LinkedList<Character> UserInput = new LinkedList<>();
//Adds Each numeral to the Array
for (int i = 0; i < s.length(); i++) {
char userint = s.charAt(i);
UserInput.add(userint);
}
//loop through the array backwards and adds up the count.
for(int j =UserInput.toArray().length -1; j> -1 ; j--) {
int grab = RomanNums.get(UserInput.get(j));
count += grab;
// Checks for 4s and 9s.
if(grab == RomanNums.get('X') && (j - 1) == RomanNums.get('I')) {
count -= 2;
}
}
System.out.println(count);
Comparing j - 1 -- which is a position in a string -- to the value of a roman numeral does not seem to make any sense.
Specifically, it only works when the roman 'I' is the second character, exactly.
What you really want to be testing is whether the character at the (j-1)'th position is 'I'.
The correct formulation should be something like
if (grab == RomanNums.get('X') &&
j > 0 &&
UserInput.get(j-1) == 'I') ...
This was my solution for leetcode: https://leetcode.com/problems/roman-to-integer/
You have the right idea about reading the input backwards and one loop should be enough to get the job done.
All you need to do is account for the cases when you have to subtract the roman numeral, and you can do that by keeping track of the previous roman numeral for comparison.
For example when input string is: "IX"
We start at 'X' in the first iteration and since previous is equal to '?' we just add 10 and set previous to 'X'. Now when we attempt to sum up 'I' in the next iteration, we look at previous and notice that it is an 'X' and instead of adding 1 to the running sum , we should subtract 1. The total should be 9.
public int romanToInt(String s) {
int sum = 0;
char prev = '?';
for(int i = s.length()-1;i >= 0;i--) {
switch(s.charAt(i)) {
case 'I' : sum += prev == 'V' || prev == 'X' ? -1 : 1;
break;
case 'V' : sum += 5;
break;
case 'X' : sum += prev == 'L' || prev == 'C' ? -10 : 10;
break;
case 'L' : sum += 50;
break;
case 'C' : sum += prev == 'D' || prev == 'M' ? -100 : 100;
break;
case 'D' : sum += 500;
break;
case 'M' : sum += 1000;
break;
default :
break;
}
prev = s.charAt(i);
}
return sum;
}
Time complexity is O(n) - Iterated the length of the input string
Space complexity is O(1) - No additional data structure was needed
I am new to programming in java (and programming in general), and was wondering if there was an easier way to say this. Basically, I'm just trying to assign numbers to letters. This is the only way I know of how to do this, but I'm sure there's a much simpler way to do this in java. Thank you for any help the community can give me.
Note: codeLetter is a char, and remainder is an int.
if (remainder <= 0)
{
codeLetter = 'A';
}
else if (remainder <= 1)
{
codeLetter = 'B';
}
else if (remainder <= 2)
{
codeLetter = 'C';
}
else if (remainder <= 3)
{
codeLetter = 'D';
}
else if (remainder <= 4)
{
codeLetter = 'E';
}
etc...
If your remainder is less then or equal to 26, you could use -
codeLetter = (char) ('A' + remainder);
If letter assignments are alphabetical, you can rely on the fact that UNICODE code points for Latin letters are alphabetized. If you need to define an arbitrary assignment, you could use a String as a "key": put the letters that you want to encode in a string, ordering them by remainder, and use charAt to extract the corresponding letter:
// Let's say you want to re-order your letters in some special way
String key = "QWERTYUIOPASDFGHJKLZXCVBNM";
// Now you can obtain the letter like this:
char letter = key.charAt(remainder);
Try using switch. Or use Character.getNumericValue() if you don't need to assign the numeric value yourself.
Or see this post which may be the most appropriate: making use of the ASCII representation of the characters.
if(remainder <= 0)
codeLetter = 'A';
else
codeLetter = 'A' + remainder;
This covers the case where remainder is negative.
public static char determineGrade(float grade)
{
char letter;
if(grade>=90 && grade<=100)
{
letter='A';
}
else if(grade>=80 && grade<=89)
{
letter='B';
}
else if(grade>=70 && grade<=79)
{
letter='C';
}
else if(grade>=60 && grade<=79)
{
letter='D';
}
else if(grade<=59)
{
letter='F';
}
return letter;
}
The program keeps telling me to initialize letter but I do not understand why I need to. Thank you.
Why I am getting an error to initialize letter and how do I fix it?
The problem is that it is possible to reach the return statement without a value having been assigned to letter. (This happens when grade is greater than 100.0. While that might not make sense in the context of your application, the Java compiler cannot know that.)
People have suggested returning a "default" value. I think that is wrong, unless the API spec defines a default value. (And, IMO, it is bad API design to do that.)
I think that a better approach is to throw an exception (for example IllegalArgumentException) if the argument provided makes no sense.
public static char determineGrade(float grade) {
if (grade >= 90 && grade <= 100) {
return 'A';
} else if (grade >= 80 && grade <= 89) {
return 'B';
} else if (grade >= 70 && grade <= 79) {
return 'C';
} else if (grade >= 60 && grade <= 79) {
return 'D';
} else if (grade >= 0 && grade <= 59) {
return 'F';
} else {
throw new IllegalArgumentException("grade is out of range: " + grade);
}
}
The other design issue here is whether it is appropriate to use floating point numbers to represent grades. There is a risk that the computation that calculates the grades gives values that are a tiny bit "off" due to rounding error; i.e. 89.999998 instead of 90.0. If you are going to use a floating point type here, you need to use threshold comparisons rather than simple >= and <= against an integer value.
The problem is :
else if(grade<=59)
{
letter='F';
}
Should be
else
{
letter='F';
}
Because you have a series of if condition, so the compiler cannot know that whether a condition will be true in run time. So either you need to declare a default value for letter or the last else should not have any condition.
For grade over 100, there should be some check to handle this.
if grade over 100 is not acceptable, an exception should be thrown at the beginning of the method (as rule of thumb):
if(grade > 100){
throw new IllegalArgumentException("Invalid input"):
}
char letter simply declares a variable of type char. Initialising means assigning it an initial value, before the variable is acted upon elsewhere in the program.
In your case, if grade is not in any of the ranges that you explicitly check for, letter needs a default value that your method can return. Since this is a local variable in your method, compiler will not assign the standard default value for char, as mentioned in this excerpt from the documentation:
Local variables are slightly different; the compiler never assigns a default value to an uninitialized local variable. If you cannot initialize your local variable where it is declared, make sure to assign it a value before you attempt to use it. Accessing an uninitialized local variable will result in a compile-time error.
That is why you need to explicitly initialise it.
Try this,
public static char determineGrade(float grade) {
char letter = 0;
if (grade >= 90 && grade <= 100) {
letter = 'A';
} else if (grade >= 80 && grade <= 89) {
letter = 'B';
} else if (grade >= 70 && grade <= 79) {
letter = 'C';
} else if (grade >= 60 && grade <= 79) {
letter = 'D';
} else if (grade <= 59) {
letter = 'F';
}
return letter;
}
there is a situation where all if statements are not executing (when number >100 ). Then letter variable doesn't have a value.To prevent that the letter variable should be initialized with a default value.
Because the char is only given values in if statements the method does not know if it will ever be given a value (it assumes there is a chance that none of if statements will have a true condition) and therefore you are requested to give an initial value.
Another way around it would be by turning the last else if statement to just an else because it covers all if the remaining possibilities anyway.
C++ has a very handy switch statement, but I don't know if this is possible is java
switch(num)
{
case 1 ... 9:
do something
break
case 10 ... 19:
do something
break
default: something
}
is this possible in java, I've tried, but it doesn't work, at least not like c++, is there an equivalent for this?
thanks
Java's switch statement requires you to explicitly list all values that you match (except for the default: clause, of course). If you're doing substantial ranges, it is probably better to use a chain of ifs:
if (num >= 1 && num <= 9) {
do_something_A
} else if (num >= 10 && num <= 19) {
do_something_B
} else {
do_something_C
}
If your real num has side effects (or is plain expensive to compute), evaluate it once and save it to a local variable, then use that local in the chain of tests.
No, it's not possible. Probably the most straightforward equivalent is:
if (num >= 1 && num <= 9)
doSomething();
else if (num >= 10 && num <= 19)
doSomethingElse();
else
doDefault();
Marginal cleanup could be defining an inRange utility function and using it inside the if statements:
boolean inRange(int num, int min, int max) {
return num >= min && num <= max;
}
...
if (inRange(num, 1, 9))
doSomething();
else if (inRange(num, 10, 19))
doSomethingElse();
else
doDefault();
Java have switch statement, but you have to use it in this way :
switch(num)
{
case 1:
case 2:
case 3:
case 4:
//And so far with cases
//do something
break
case 10:
case 11:
case 12:
//And so far ...
//do something
break
default: something
}
Yes, there is a switch statement in Java. It is in fact quite similar to switch in C++.
However, neither C++ nor Java support ranges in case labels.
For the specific example that you present I would use a series of if statements:
if (num >= 1 && num <= 9) {
...
} else if (num >= 10 && num <= 19) {
...
} else {
...
}
No Java does not, in a situation like this it would be much more practical to use a series of if-else statements. :)
if(num >= 1 && num < 10) {
//do something
} else if(num >= 10 && num < 20) {
//do something
} else {
//do something
}
The feature you are talking about doesn't really belong to C++, it is a language extension which is present, for example, in GCC. But normally in C++ ranges are checked using if...else, and the same technique should be used in Java:
if (num >= 1 && num <= 9) {
//Do something
} else if (num >= 10 && num <= 19) {
//Do something else
} else {
//Do something by default
}
No, ranges are not allowed you would need to use an if else structure.
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.