Explain if block nesting - java

This is regarding some homework and I tried to make a range which is 10 to 40.
The code would accept two inputs within the range. The method will then check if both numbers are within the range and then if they are it would give me the product of both numbers, if not it is suppose to show me a message.
I have been working on this for quite a long time and I cant get it to work I am a complete beginner.
public class testing
{
public static int computeProduct(int first , int second)
{ int max = 40;
int min = 10;
int total = first * second;
if (min <= first) {
if (first <= max) {
if (min <= second) {
if (second <= max) {
total = first * second;
} else {
System.out.println("Number is not in range, please try again");
}
}
}
}
return total;
}
public static void main(String[] args)
{
Scanner scanner = new Scanner(System.in);
System.out.println("Enter a number between 10 to 40:");
int x = scanner.nextInt();
System.out.println("Enter another number between 10 to 40:");
int y = scanner.nextInt();
int total = computeProduct(x, y);
System.out.print("Product of x and y = " + total);
}
}
Expected result is to show me if the numbers are not in range but it is not doing so currently.
It gives me the product of both numbers regardless whether it is in the range.

Here:
int total = first * second;
followed by an if, follewed by:
return total;
Meaning: every time when your if evaluates to false, your method simply returns the value that you assigned initially!
What you could do: have an else block that prints the error message. Or that throws an exception.
But ideally, you should separate concerns here. Meaning:
write a method like boolean inRange(int first, int second). That method returns true or false, depending on first / second matching your criteria
if that method returns true, call compute(), otherwise print your message
In other words: your compute() method maybe shouldn't have that if block at all. Let that method compute the result, and have another method tell you whether you want to invoke compute() or not.

A "ladder" built from ifs behaves as a logical and relation. The first if passes when a condition applies, then the second if passes when both the previous condition applies and its own condition, and so on.
However for checking if something is off, violating any (even a single one) of the rules is enough, that is a logical or relation.
While it is not the best coding style, you could mechanically rewrite that structure into this via flipping the comparisions and dismantling the ladder:
public static int computeProduct(int first , int second)
{
int max = 40;
int min = 10;
if (first < min) {
System.out.println("Number is not in range, please try again");
return 0;
}
if (first > max) {
System.out.println("Number is not in range, please try again");
return 0;
}
if (second < min) {
System.out.println("Number is not in range, please try again");
return 0;
}
if (second > max) {
System.out.println("Number is not in range, please try again");
return 0;
}
return first*second;
}
This method displays the message and returns with 0 if the input is not valid, and returns the product if everything is fine.
Then it could become an actual logical or, which is denoted as || in Java:
public static int computeProduct(int first , int second)
{
int max = 40;
int min = 10;
if (first < min
|| first > max
|| second < min
|| second > max) {
System.out.println("Number is not in range, please try again");
return 0;
}
return first*second;
}
Now as I think of it, there is nothing wrong with your original condition either, just the result has to be flipped: when the code reaches the innermost block, everything is fine, so that is the place where you could return first*second;. And if any of the if fails, you need the message and return 0;:
public static int computeProduct(int first , int second)
{
int max = 40;
int min = 10;
if (min <= first) {
if (first <= max) {
if (min <= second) {
if (second <= max) {
return first*second;
}
}
}
}
System.out.println("Number is not in range, please try again");
return 0;
}
Now I am not so sure if this helps or not...

There you go :
public static int computeProduct(int first , int second)
{ int max = 40;
int min = 10;
if(first<=min || second<=min ||first>=max||second>=max)
{
System.out.println("Number is not in range, please try again");
return 0; //or return whatever you like
}
return first *second ;
}
public static void main(String[] args)
{
Scanner scanner = new Scanner(System.in);
System.out.println("Enter a number between 10 to 40:");
int x = scanner.nextInt();
System.out.println("Enter another number between 10 to 40:");
int y = scanner.nextInt();
int total = computeProduct(x, y);
if(total!=0){
System.out.print("Product of x and y = " + total);
}
else {
System.out.print("cannot compute as numbers are not in range");
}
}

Related

Returns the length of the longest sequence of identical digits found in num recursive

I had an assignement;
"Write a recursive static method that accepts a positive integer num and returns the length of the longest sequence of identical digits found in num."
This is the solution I did
public static int equalDigits (int num)
{
return equalDigits(num,1,0);
}
private static int equalDigits (int num, int count, int max){
if (num < 10)
return 1;
if (num/10%10 == num%10)
count++;
else
count = 1;
max = count > max ? count : max;
return Math.max(max,equalDigits(num/10,count,max));
}
But my lecturer said it can be done without using helper method.
I can't figured how exactly it's possible.
Here is some code using your methodology, so without using String (which I would consider ugly):
public static int equalDigits(int num)
{
// this is a so-called guard statement at the start to disallow invalid arguments
if (num < 0) {
throw new IllegalArgumentException("Expecting positive value or zero");
}
int currentDigit = -1; // "magic value" outside of range
int count = 0;
int maxCount = 0;
int x = num; // good practice not to operate on parameters
while (x > 0) {
int digit = x % 10;
if (digit == currentDigit) {
count++;
} else {
// only update max count when needed
// TODO set maxcount
// TODO something with digits
// don't forget the initial digit, so not zero
// TODO set initial count
}
x /= 10; // yes, it exists, is identical to x = x / 10
}
// if the last count was higher we still need to adjust
// TODO set maxcount
return maxCount;
}
I've removed the stuff that you need to get it to work, but I've shown how you can do this without recursive operations, as that can be hard to refactor.

How to prevent a recursive method from changing a value of a variable?

I'm learning Java, and I'm stuck on a recursion problem.
I need to use a recursive method to check if a number is an Armstrong number or not.
My code:
public class ArmstrongChecker {
public boolean isArmstrong(int number) {
// check if the number is a negative number
if (number < 0) {
return false;
}
ArmstrongChecker armstrongChecker = new ArmstrongChecker();
// find the length of the number
int length = armstrongChecker.lengthChecker(number);
// create a variable to store the sum of the digits of the number
int sum = 0;
// find the individual digits and raise to the power of the numbers of digits
if (number != 0) {
int digit = Math.floorMod(number, 10);
int powerRaised = (int) Math.pow(digit, length);
sum = sum + powerRaised;
isArmstrong(number / 10);
}
return sum == number;
}
// method to check the length of the number
public int lengthChecker(int number) {
int length = String.valueOf(number).length();
return length;
}
}
How do I prevent int length in isArmstrong() method from changing its value.
While you are not changing it's value in the posted code, you could mark that variable to be a constant. This way the compiler can error out if you tried to assign a new value.
final int length = armstrongChecker.lengthChecker(number);
As I've already said in the comments, your solution has the following issues:
The result of the recursive call isArmstrong() is being ignored;
There's no need for spawning new instances of ArmstrongChecker. And this method doesn't require object creation at all, it can be implemented as static.
Checking if the number is an Armstrong number boils down to calculating its Armstrong sum, the solution will be cleaner if you implement only this part using recursion.
It might look like this:
public static boolean isArmstrong(int number) {
if (number < 0) return false;
if (number < 10) return true;
return number == getArmstrongSum(number, String.valueOf(number).length());
}
public static int getArmstrongSum(int number, int power) {
if (number == 0) {
return 0;
}
return (int) Math.pow(number % 10, power) + getArmstrongSum(number / 10, power);
}
main()
public static void main(String[] args) {
System.out.println(isArmstrong(370)); // true
System.out.println(isArmstrong(12)); // false
System.out.println(isArmstrong(54)); // false
System.out.println(isArmstrong(153)); // true
}
Output:
true
false
false
true
You need to get the length once for whole recursion, so the cleanest approach would be to pass down both the number and the length into the recursion. An easy way to do this is to have one method that is the public face of the API, and another that does the recursion.
public class ArmstrongChecker {
public boolean isArmstrong(int number) {
if (number < 0) {
return false;
}
int length = lengthChecker(number);
int sum = armstrongSum(number, length);
return sum == number;
}
private int armstrongSum(int number, int length) {
int sum = 0;
if (number != 0) {
int digit = Math.floorMod(number, 10);
int powerRaised = (int) Math.pow(digit, length);
sum += powerRaised;
sum += armstrongSum(number / 10, length);
}
return sum;
}
public int lengthChecker(int number) {
int length = String.valueOf(number).length();
return length;
}
}
This is pretty common in recursion, where the parameters to the recursive part of the algorithm are a little different (usually there are more of them) than what you want a client of the API to have to pass in. The number changes in each recursive call, where number / 10 is passed down, but the same length is passed all the way through.
Notice that the recursive armstrongSum uses the return value from the recursive call, and that there is no need to create another instance of ArmstrongChecker when you are already in an instance method of the class.

Why Does my Palindrome Code not work? My reverse variable does what it is supposed to but I dont get true even when it is printing out a palindrome

public class NumberPalindrome {
public static boolean isPalindrome(int number) {
int reverse = 0;
if (number<0){
number=number* -1;
}
while (number > 0) {
int lastDig = number % 10;
reverse = lastDig + reverse;
if (number<10) {break;}
reverse = reverse * 10 ;
number/=10;
}
if (number==reverse) {
return true;
}
return false;
}
}
why does my code not return true when I enter a palindrome number? I tried using it to print out the reverse value and it does it quite well, but just does not seem to get the boolean value straight though.
The problem was modifying the number variable, but then comparing it with the new generated reverse variable as if it was never edited.
Also, you were adding the last digit to the reverse variable before multiplying it by ten.
See the following code in Java:
public static boolean isPalindrome(int number) {
int reverse = 0;
if(number < 0) {
number *= -1;
}
int initialNumber = number;
while(number > 0) {
int lastDigit = number % 10;
reverse = (reverse * 10) + lastDigit;
if(number < 10) {
break;
}
number /= 10;
}
return initialNumber == reverse;
}
There are a few problems here. You need to save the original number for comparison with the the reversed number. The break statement confuses the logic.
To figure this out, I added some print statements to trace the progress. Adding print statements isn't elegant, but it is very useful.
Here is my version, with comments indicating what I changed.
public static boolean isPalindrome (int original)
{
// Need to save the original number for comparison
int number = original;
int reverse = 0;
if (number < 0)
{
number = number * -1;
}
while (number > 0)
{
int lastDig = number % 10;
// Update and shift reverse in one step
reverse = lastDig + reverse * 10;
number /= 10;
// Don't need extra break to terminate the loop
System.out.printf ("Check %d ; Reverse %d%n", number, reverse);
}
System.out.printf ("Final %d ; Reverse %d%n", number, reverse);
// Compare to original and return boolean value directly
return (original == reverse);
}

Why is code skipping over for loop in integer length program

Im trying to create a program to find the length of a given number. I thought i would do this by taking the number and dividing by 10 and then checking to see if the number was <= 0. I dident want to edit the global number so i created a instance version of the number and used that as the condition in the for loop.
So obviously this dident work so naturally i ended up looking in the debugger to figure out what was going on. It looks as if the program is completely skipping over the for loop any help would be appreciated.
public static void sumFirstAndLastDigit(int number) {
int numberLength = 0;
int instanceNumber = number;
for(int i = 0; instanceNumber <= 0; i++) {
instanceNumber /= 10;
numberLength = i;
}
System.out.println("Number length = " + numberLength);
// to find length of number loop division by 10
}
}
The program should use the for loop to keep dividing by 10 until the number is = to or less than than zero and for how many times the loop ran should be stored in the number length integer. In this case with the number 12321 the answer should be 6 but it prints 0.
You're telling it to loop while instanceNumber <= 0. The "test" in a for loop is a "keep going" test, not a termination test. The loop continues as long as the test is true.
From your description, you want instanceNumber > 0.
Also note Avinash Gupta's point that with your current code, you'll undercount by one. I'd address that by using a completely different loop:
int numberLength = 0;
int instanceNumber = number;
while (instanceNumber > 0) {
++numberLength;
instanceNumber /= 10;
}
That's nice and unambiguous: If instanceNumber > 0, it increments numberLength, then divides by 10 and tries again.
This will print the correct output
public static void sumFirstAndLastDigit(int number) {
int numberLength = 0;
int instanceNumber = number;
for(int i = 0; instanceNumber > 0; i++) {
instanceNumber /= 10;
numberLength = i;
}
System.out.println("Number length = " + (numberLength + 1));
}
Your code will be much more comprehensive if you use while loop for your algorithm.
public static void sumFirstAndLastDigit(int number) {
int numberLength = 0;
int instanceNumber = number;
while(instanceNumber != 0) {
instanceNumber /= 10;
numberLength += 1;
}
System.out.println("Number length = " + numberLength);
// to find length of number loop division by 10
}
Consider even more sophisticated solution:
public static void sumFirstAndLastDigit(int number) {
int numberLength = (int) (Math.log10(number) + 1);
System.out.println("Number length = " + numberLength);
}
Taken from Baeldung

Java Average Program

Write a class called Average that can be used to calculate average of several integers. It should contain the following methods:
A method that accepts two integer parameters and returns their average.
A method that accepts three integer parameters and returns their average.
A method that accepts two integer parameters that represent a range.
Issue an error message and return zero if the second parameter is less than the first one. Otherwise, the method should return the average of the integers in that range (inclusive).
Implement the class and write a program to test its methods and submit your source code (.java files).
I am stuck on part three, I don't even really understand the stipulation. Will I be using a floating point / double? Here is the program I have thus far:
import java.util.Scanner;
public class Average {
public static void main(String[] args) {
int numb1, numb2, numb3, userInput;
System.out.println("Enter '2' if you wish to average two numbers enter '3' if you wish to average 3.");
Scanner keyboard = new Scanner(System.in);
userInput = keyboard.nextInt();
if (userInput == 2){
System.out.println("Enter two numbers you'd like to be averaged.");
numb1 = keyboard.nextInt();
numb2 = keyboard.nextInt();
Average ave = new Average();
System.out.println("The average is: " + ave.average(numb1, numb2));
System.exit(1);
}
if(userInput == 3){
System.out.println("Enter three numbers you'd like to be averaged.");
numb1 = keyboard.nextInt();
numb2 = keyboard.nextInt();
numb3 = keyboard.nextInt();
Average ave = new Average();
System.out.println("The average is: " + ave.average(numb1, numb2, numb3));
System.exit(1);
}
}
public static int average (int num1, int num2) {
return (num1 + num2) / 2;
}
public static int average (int numb1, int numb2, int numb3){
return (numb1 + numb2 + numb3) / 3;
}
}
Please don't re-ask the same question as you just asked here: http://stackoverflow.com/questions/19507108/java-averaging-program
Rather update your other post to reflect your new code / questions.
Now onto your question:
A method that accepts two integer parameters that represent a range. Issue an error message and return zero if the second parameter is less than the first one. Otherwise, the method should return the average of the integers in that range (inclusive). Implement the class and write a program to test its methods and submit your source code (.java files).
Lets start by declaring our method and we'll declare it as static to conform to your program (since you're not creating your own objects). Then we want to check if the parameters follow the assignment instructions and return values accordingly.
public static int getRange(int firstValue, int secondValue)
{
int range;
if (firstValue > secondValue)
range = firstValue - secondValue;
else
{
range = 0;
System.out.println("Error!");
}
return range;
}
**To promote your understanding it's up to you to find the average of the integers in the range!
Not really here to do your homework, but since I'm already here, the range is the difference between the largest and smallest number.
public int returnRange(int first, int second) {
if(first > second)
return first-second;
else
return second-first;
}
To make things easier though...
public double returnAverage(int...numbers) {
for(int i = 0; i < numbers.length(); i++) {
total += numbers;
}
return total/numbers.length();
}
public int returnRange(int...numbers) {
int holder = 0;
int highest;
int lowest;
for(int i = 0; i < numbers.length(); i++) {
if(numbers[i] > holder) {
holder = numbers[i];
}
highest = holder;
for(int i = 0; i < numbers.length(); i++) {
if(numbers[i] < holder) {
holder = numbers[i];
}
}
lowest = holder;
return highest-lowest;
}
Last 2 methods are un-tested, but from experience, should work fine. These methods have arrays for the parameters, so you can do as many numbers as you'd like.
In your main method check for -1 and return error when first value is greater than second
public double avgRange(int a, int b){
if(a>b){
return -1;
}
else{
double total=0;
for(int x=a; x<=b; x++){
total = total + x;
}
return total/(b-a+1);
}
}
the method should return the average of the integers in that range (inclusive).
You're asked to return the average of all integers in the range bounded by the two parameters.
For example, if parameters were 5 and 10, the method should return the average of 5, 6, 7, 8, 9, and 10, which is 7.5. (5 and 10 are included because the question says the range should be "inclusive".)
To find the average, use a for loop to sum each integer in the range, then divide by the number of integers.
Will I be using a floating point / double?
The return value should be a float or double, since the average isn't always a whole number.

Categories

Resources