Using a recursive method instead of a while loop - java

I'm working on a project for a Java 2 class which has to show population growth of organisms for a period of days inputted by the user. I was able to implement the method using a while loop, but am having difficulty converting it to a recursive method.
while(day <= totalDays)
{
if (day == 1){
System.out.println(organs);
day++; //day one there is no increase
}
else{
organs = organs + organs*(increase/100); //add % increase of organisms
System.out.println(organs);
day++;}
}
Here is my unsuccessful attempt at a recursive method so far.
public static double showPopulation(int dayNum, int days, double organisms,
double dailyIncrease)
{
if(dayNum == totalDays)
{
return organisms + (organisms*dailyIncrease);
}
else
return showPopulation(dayNum+1, days, organisms, dailyIncrease) + organisms*dailyIncrease;

public int population(int days, int startingOrganisms, double dailyIncrease) {
if (days <= 1) {
System.out.print(days + " " + startingOrganisms);
//no increase, finish condition
return startingOrganisms;
} else {
// we need to find the population of yesterday to know how much organisms exist today
int populationYesterday = population(days - 1, startingOrganisms, dailyIncrease);
int populationToday = populationYesterday + (populationYesterday * dailyIncrease / 100);
System.out.print(days + " " + populationToday);
return populationToday;
}
}
And then just invoke it and print the result
System.out.println( population(10, 1000, 30.2);
Do you need to print the growth each each step of the way?

While I guess thisis for Homework, here is how it should work
public static double showPopulation(int dayNum, double organisms,
double dailyIncrease)
{
if(dayNum == 1)
{
return organisms + (organisms*dailyIncrease);
}else{
return showPopulation(dayNum-1, organisms, dailyIncrease) + organisms*dailyIncrease;
}
}
I did not run it, so beware of further bugs.
You forgot the termination condition. It must always get a step closer to this condition, usually by decreasing until reaching 0 or similar.

try this code:
public static double showPopulation(int totalDay,int days, double organisms,
double dailyIncrease) {
if(days == totalDay) {
return organisms;
}
else{
organisms+=organisms*dailyIncrease;
return showPopulation(totalDay,++days, organisms, dailyIncrease);
}
}

Call the following function by showPopulation(totalDays, organ, dailyIncrease). Here I am assuming totalDays is the entire number of days, organ is the initial value of the "organs", and dailyIncrease is a percentage.
public static double showPopulation(int dayNum, double organ, double dailyIncrease) {
if(dayNum <= 1) {
return organ;
} else {
return (1 + dailyIncrease) * showPopulation(dayNum - 1, organ, dailyIncrease);
}
}
Generally, when using iteration we usually start from the base case. In terms of this question, it means day 1, or when dayNum == 1. Whereas when applying recursion, we usually start considering the problem from the final state of the procedures. In this problem, it means the last day (totalDays).

Related

How to get my rate values to display correctly?

I finally got my program to compile without any errors and the first half is correct the total pay, retirement deduction and net pay were all displaying 0. I saw from a different post that Java doesn't analyze the logic of your if blocks so I edited my code to have my rate assigned to 0 and my if statement to return rate. I'm now getting the error "unexpected return value". How do I get my program to have the appropriate value depending on the user's input?
import java.util.*;
public class AcmePay {
public static void main(String[] args) throws Exception {
Scanner keyboard = new Scanner(System.in);
double hours;
int shift;
int plan;
double rate = 0;
double overtimePay;
double paycheck;
//double retirement;
// double retirement = paycheck - (paycheck * .03);
//double netPay = paycheck - retirement;
System.out.println("How many hours did you work this week?");
hours = keyboard.nextDouble();
if ( hours <= 40 )
{
paycheck = hours * rate;
}
else
{
paycheck = (40 * rate) + ((hours - 40)) * (rate*1.5);
}
System.out.println("What shift did you work? 1, 2, or 3?");
shift = keyboard.nextInt();
if (shift == 1)
{
rate = 17;
return rate;
}
else if (shift == 2)
{
rate = 18.50;
return rate;
}
else if (shift == 3)
{
rate = 22;
return rate;
}
To print the rate, the last part of your code can be like this:
shift = keyboard.nextInt();
if (shift == 1) {
rate = 17;
} else if (shift == 2) {
rate = 18.50;
} else if (shift == 3) {
rate = 22;
}
System.out.println("Rate = " + rate);
i.e. remove the return statements and then print the rate at the end. You can't return a value from a void method like main(), hence the error.
If you want to calculate the rate using a separate method, you would do something like this:
private static double rateForShift(int shift) {
if (shift == 1) {
return 17;
} else if (shift == 2) {
return 18.50;
} else if (shift == 3) {
return 22;
}
return 0;
}
This method returns a double, so now you can (and have to) use return statements.
You would call it from the main method with:
double rate = rateForShift(shift);
It's a good idea to split your code into focused methods, like this, because it makes it easier to read and work with.
I think your code has a "logic" bug in it because you are using the rate variable to calclulate paycheck, but the rate variable is always 0 at the point you use it. You should probably ask both questions before you calculate the paycheck amount.
A full program would look like this:
public static void main(String[] args) {
Scanner keyboard = new Scanner(System.in);
System.out.println("How many hours did you work this week?");
double hours = keyboard.nextDouble();
System.out.println("What shift did you work? 1, 2, or 3?");
int shift = keyboard.nextInt();
double paycheck = calculatePayCheck(rateForShift(shift), hours);
System.out.println("Paycheck = $" + paycheck);
}
private static double calculatePayCheck(double rate, double hours) {
if (hours <= 40) {
return hours * rate;
} else {
return (40 * rate) + ((hours - 40) * (rate * 1.5));
}
}
private static double rateForShift(int shift) {
if (shift == 1) {
return 17;
} else if (shift == 2) {
return 18.50;
} else if (shift == 3) {
return 22;
}
return 0;
}
In Java programs you don't need to declare your variables at the top. The convention is to declare them as you need them.
Example
How many hours did you work this week?
20
What shift did you work? 1, 2, or 3?
2
Paycheck = $370.0
It's also worth mentioning that, although fine for a toy example, in a real system you should not use floating point numbers (like double) to represent money.
ELEVATE covered the code, so I'll cover the theory.
In Java (and in many other programming languages), a method is a block of code that may or may not take in an input and may or may not give an output. Whether or not the method gives an output can be determined by analyzing the method definition. If a primitive type (for example, int or double) or Object (for example, Scanner) is used in the method definition, then that method will return that type as output. If the keyword void is used in the method definition, then that method will return no output.
A key point to understand is this: Once a method is told to return a value, that method will terminate. Thus, you cannot include any code after a return statement, or your compiler will be angry with you and yell at you for including "unreachable code."
Now, to apply this to the specifics. The main method in Java uses the keyword void to indicate that it will not return any sort of output. Thus, return rate; is inappropriate for two reasons:
Returning a double value is indeed some sort of output, which contradicts the method definition of main in which main was set to return no output by the keyword void.
return rate; will cause your program to terminate immediately. Assuming that ELEVATE was correct about how you should reorder your code, leaving a return statement in your answer would cause you further problems by preventing your code from moving on to calculate your paycheck.
Side Note: A method that returns no output can still use the return keyword, but it cannot be used with any sort of value or object. For example, the following method is valid because return isn't paired with any sort of value.
public class ReturnExample {
/*Other stuff.*/
public void returnNothing() {
System.out.println("Now returning nothing.");
return;
}
}
}

how can I take one methods result as another methods' parameter

I need to take this "over" statement under the overallmethod as finalmethods' parameter, how can I do this. I want to learn the final letter but to do that I want to access over statement.
public static void overallmethod(int quiz1,int quiz2,int quiz3,int midterm,int grade){
double quizzes = ( ((quiz1*10) + (quiz2*10) + (quiz3*10)) *25) /300;
double finalg = ( grade * 40) / 100;
double mid = (midterm * 35) / 100;
double over = quizzes + finalg + mid;
System.out.println("Your overall score is: " + over);
}
public static void finalmethod(double over){
if(over <= 100 && over >= 90){
System.out.println("Your final letter is: A");
}
else if(over >= 80) {
System.out.println("Your final letter is: B");
}
else if (over >= 70) {
System.out.println("Your final letter is: C");
}
else if (over >= 60) {
System.out.println("Your final letter is: D");
}
else{
System.out.println("Your final letter is: F");
}
}
You're going to need to return the variable over and change your return type to double.
public static double overallmethod(int quiz1,int quiz2,int quiz3,int midterm,int grade)
{
//Your code
return over;
}
Then simply pass the value returned from the overallmethod to finalmethod.
over is not a statement, it is a local variable now. Just make it class attribute:
public static double over
Make your overall function return the value of over. Then just call the overall function inside the parameter list of finalmethod
The best solution would be to declare over as a private int outside both the methods, i.e. it should have visibility to all the methods in that class (class variable).
Now compute the overall score in the overallMethod and store it to the over variable.
Next, make a public method getOver() which returns the value of over, and call finalMethod in this way : ClassName.finalMethod(objectOfClass.getOver())
By changing the return type of your method to double, and then passing the value in that method to the final method.

Using recursion to compute factorials without new variables [duplicate]

This question already has answers here:
Recursion vs For loops - Factorials, Java
(3 answers)
Closed 6 years ago.
I am trying to compute the entered factorial in the method factorialRecursive by using recursion, However I cannot declare any variables or objects in that method and thats what i am struggling with, my attempt is in the method already but doesn't work. This has to call itself in a While loop not a for loop.
class Factorial{
public static void main(String[] args){
Scanner input = new Scanner(System.in);
int number;
do {
System.out.print("Enter a positive number: ");
number = input.nextInt();
} while (number < 0);
System.out.println(number + "! = " + factorialIterative(number) + " (iterative)");
System.out.println(number + "! = " + factorialRecursive(number) + " (recursive)");
}
private static int factorialIterative(int num) {
int result = 1;
while (num > 0) {
result = num*result;
num--;
}
return result;
}
private static int factorialRecursive(int num){
if (num==1 | num==0)
return 1;
return num*(num-1) * num;
}
}
Try this:
private static int factorialRecursive(int num) {
// Warning here use || instead of |
if (num==1 || num==0)
return 1;
return num * factorialRecursive(num - 1);
}
I can also be simplified like this:
private static int factorialRecursive(int num) {
return (num == 1 || num == 0) ? 1 : num * factorialRecursive(num - 1);
}
You don't need to declare any variables. Take advantage of the recurrence relation for factorials:
n! = n * (n - 1)!
Multiply num by the result of making a recursive call by passing num - 1. Return that product without storing it in a variable.
Recursivity means you need to call the method itself inside of the method
Example:
private static int factorialRecursive(int num){
if (num==1 | num==0)
return 1;
return num*factorialRecursive(num-1);
}
and since factorial will increase really high with low values, consider to use other data type than integers... otherwise it will only work until factorial(16) after that you will get invalid data by using ints...
private static long factorialRecursive(long num){
if (num==1 | num==0)
return 1;
return num*factorialRecursive(num-1);
}

How to write toString() and equals() methods?

I'm trying to make this piece of code print the actual numbers, and not the hexadecimal location.
public class MoneyDriver
{
//This is a driver for testing the class
public static void main(String[] args)
{
final int BEGINNING = 500;
final Money FIRST_AMOUNT = new Money(10.02);
final Money SECOND_AMOUNT = new Money(10.02);
final Money THIRD_AMOUNT = new Money(10.88);
Money balance = new Money(BEGINNING);
System.out.println("The current amount is " +
balance.toString());
balance = balance.add(SECOND_AMOUNT);
System.out.println("Adding " + SECOND_AMOUNT +
" gives " + balance.toString());
balance = balance.subtract(THIRD_AMOUNT);
System.out.println("Subtracting " + THIRD_AMOUNT +
" gives " + balance.toString());
boolean equal = SECOND_AMOUNT.equals(FIRST_AMOUNT);
if(equal)
System.out.println(SECOND_AMOUNT + " equals "
+ FIRST_AMOUNT);
else
System.out.println(SECOND_AMOUNT.toString() +
" does not equal " + FIRST_AMOUNT);
equal = THIRD_AMOUNT.equals(FIRST_AMOUNT);
if(equal)
System.out.println(THIRD_AMOUNT + " equals " +
FIRST_AMOUNT);
else
System.out.println(THIRD_AMOUNT + " does not equal "
+ FIRST_AMOUNT);
}
}
This is the main class which is called by moneydriver
public class Money
{
private long dollars;
private long cents;
public Money(double amount)
{
if (amount < 0)
{
System.out.println(
"Error: Negative amounts of money are not allowed.");
System.exit(0);
}
else
{
long allCents = Math.round(amount*100);
dollars = allCents/100;
cents = allCents%100;
}
}
public Money add(Money otherAmount)
{
Money sum = new Money(0);
sum.cents = this.cents + otherAmount.cents;
long carryDollars = sum.cents/100;
sum.cents = sum.cents%100;
sum.dollars = this.dollars
+ otherAmount.dollars + carryDollars;
return sum;
}
public Money subtract (Money amount)
{
Money difference = new Money(0);
if (this.cents < amount.cents)
{
this.dollars = this.dollars - 1;
this.cents = this.cents + 100;
}
difference.dollars = this.dollars - amount.dollars;
difference.cents = this.cents - amount.cents;
return difference;
}
public int compareTo(Money amount)
{
int value;
if(this.dollars < amount.dollars)
{
value = -1;
}
else if (this.dollars > amount.dollars)
{
value = 1;
}
else if (this.cents < amount.cents)
{
value = -1;
}
else if (this.cents > amount.cents)
{
value = 1;
}
else
{
value = 0;
}
return value;
}
}
The objectives is to write equals method (on main class). The method compares the instance variables of the calling object with instance variables of the parameter object for equality and returns true if the dollars and the cents of the calling object are the same as the dollars and the cents of the parameter object. Otherwise, it returns false.
Write toString method (on main class). This method will return a String that
looks like money, including the dollar sign. Remember that if you have less than 10 cents, you will need to put a 0 before printing the cents so that it appears correctly with 2 decimal places.
If both of the method is implemented correctly
According to tutorialspoint, you're supposed to do either
String toString()
static String toString(int i)
But the supplied moneydriver already has the tostring method, but doesn't display the numbers, instead it displays a hexadecimal location of the variable.
The equals method is already used in moneydriver, so I'm kinda lost on that too.
The correct output should look like this
The current amount is $500.00
Adding $10.02 gives $510.02 Subtracting $10.88 gives $499.1
$10.02 equals $10.02
$10.88 does not equal $10.02
Completely lost in this, thanks in advance for help.
To get a String output on the Money class, do something akin to:
public class Money
{
private long dollars;
private long cents;
// suggested approach for constructor
public Money(long amount) throws IllegalArgumentException
{
if (amount < 0) {
throw new IllegalArgumentException("Amount may not be less than 0");
}
// do other stuff
}
...
public String toString()
{
return String.format("%d.%02d", dollars, cents);
}
public boolean equals(Object obj)
{
boolean equal = false;
if (obj instanceof Money) {
Money chk = (Money)obj;
equal = (chk.dollars == this.dollars &&
chk.cents == this.cents);
}
return equal;
}
} // end class Money

Java: Performance SQRT Calculations

I have this code:
package math;
import java.io.IOException;
import java.util.Scanner;
public class Main
{
public static void main(String[] args) throws IOException
{
System.out.println("Hi, I will beat Java's Math.sqrt(double) method");
System.out.println("Both ways of calculation will be done");
System.out.println("I will time how long they took to calculate");
System.out.println("Random doubles will be generated");
System.out.println();
System.out.println("Please give the number of sqrt-calculation will be done");
int calcs = new Scanner(System.in).nextInt();
boolean output = true;
if (calcs > 10000)
{
System.out.println("You're asking much calculations");
System.out.println("Disabling output is recommend");
System.out.println("Disable output? (y/n)");
char a = (char) System.in.read();
if (a == 'y')
{
output = false;
}
}
System.out.println("Press enter to start");
System.in.read();
test(calcs, output);
System.out.println();
System.out.println("I was much faster I think");
System.out.println("Now you can check my precision");
System.out.println("Please give a complex double");
double x = Double.parseDouble(new Scanner(System.in).next());
System.out.println();
System.out.println("Math.sqrt(" + x + ") = " + Math.sqrt(x));
System.out.println("SqrtCalculator.sqrt(" + x + ") = " + sqrt(x));
System.out.println("------------------------");
System.out.println("Now please make your conclusion");
System.out.println("Thanks for trying");
}
public static void test(int calculations, boolean output)
{
double factor = Math.random() / 2;
// Math
long mathStart = System.currentTimeMillis();
for (int i = 1; i <= calculations; i++)
{
double x = i * factor;
double result = Math.sqrt(x);
if (output)
{
System.out.println("Math.sqrt(" + x + ") = " + result);
}
}
long mathStop = System.currentTimeMillis();
long mathTime = mathStop - mathStart;
// My Method
long myStart = System.currentTimeMillis();
for (int i = 1; i <= calculations; i++)
{
double x = i * factor;
double result = sqrt(x);
if (output)
{
System.out.println("SqrtCalculater.sqrt(" + x + ") = " + result);
}
}
long myStop = System.currentTimeMillis();
long myTime = myStop - myStart;
System.out.println();
if (output)
System.out.println("---------------------------");
System.out.println("Here are the results:");
System.out.println("Math and SqrtCalculator did each " + calculations + " of the same sqrt-calculations");
System.out.println();
System.out.println("Math: " + mathTime + " milliseconds");
System.out.println("I: " + myTime + " milliseconds");
}
public final static double sqrt(double x)
{
double previous = 1;
double now = 0;
for (;;)
{
now = (x / previous + previous) / 2;
if (previous == now)
{
return now;
}
previous = now;
}
}
}
This sqrt method is called "heroon".
If I run my program and I ask 80000 calculations and I disable the output, Math.sqrt() is much faster than my method. If I ask 80000 calcs and I enable the output, My method is much faster.
Can someone explain this?
Thanks
Sorry for bad English.
I could not reproduce your results. Tried some times using Eclipse Galileo and JDK 1.6.0.
For 80000, output disabled, I got something like:
Math: 15 milliseconds
I: 32 milliseconds
small times, It would be better to use System.nanoTime() or more interactions.
For 80000, output enabled:
Math: 3609 milliseconds
I: 4906 milliseconds
So probably the problem is the way that output is handled (scrolling, buffering, ...)
The Math.sqrt method defers to StrictMath.sqrt, which is done in hardware or native code. (Look at the source for the JDK - you'll see that it's a native method.) This is certainly faster than anything you'll write. It might even be using the same algorithm that you coded. It's well known. Your method is simply Newton's method for calculating square roots. It's been known since Babylon; Newton simply rederived it using calculus. Quadratic convergence is good.
Whatever you've done, it's unlikely that you've discovered anything new or noteworthy. Sounds like something having to do with IO is artificially biasing the results.
You're probably overwhelming the actual calculation time with the output time, and running into a fluke of the buffering. A profiler would show you what's actually consuming the time.
Kudos for trying to improve on an existing implementation; even if you fail, you can learn a lot about algorithms in the process. Naturally, you have to test your alternative using this kind of micro-benchmark. Unfortunately, there are numerous pitfalls. In particular, don't mix irrelevant code, e.g testing and output, with your calculation; do warm up the JVM early in your test. There's more in this article on bechmarking. Also, when comparing floating point values, consider these Guidelines for comparing floating point numbers.

Categories

Resources