הלינקייה: מגזין חודשי למפתחים

רוצה לשמוע על כל האירועים, המדריכים, הקורסים והמאמרים שנכתבו החודש ?
הלינקייה הינו מגזין חופשי בעברית שמשאיר אותך בעניינים.
בלי ספאם. בלי שטויות. פעם בחודש אצלך בתיבה.

Java Syntax Solutions

Below are selected solution for the syntax exercises both in the printed notebook and from the site. Take the time to compare your results with the suggested solution.

package ex5;
 
/**
 * A Leap Year class represents a year
 * In the constructor, it randomizes a number
 * for the year. 
 * Later on, it can return that year, or answer
 * if it is leaped
 *
 */
public class LeapYear {
	private int year;
 
	public LeapYear() {
		this.year = (int) ( Math.random() * 2010 );		
	}
 
	/**
	 * A year is leap if one of these is true:
	 * Dividable by 4 AND not dividable by 100
	 * Dividable by 100 AND dividable by 400
	 */
 
	public boolean isLeap() {
		if ( this.year % 100 == 0 ) {
			return ( this.year % 100 == 0 ); 
		} else {
			return ( this.year % 4 == 0 );
		}
	}
 
	public int getYear() {
		return this.year;
	}
}
package ex5;
 
import junit.framework.TestCase;
 
 
public class LeapYearTest extends TestCase {
 
	public void testLeap() {
		LeapYear y = new LeapYear();
 
		System.out.println("Year = " + y.getYear());
 
		if ( y.isLeap() ) {
			System.out.println("year is leap");
		} else {
			System.out.println("year is not leap");
		}
	}
}

Exercise 5-4 Salary Raiser

Raising a salary is not as intuitive as it may seem. Since in java, floats and doubles are designed mostly for engineering calculations, they handle money rather poorly.

For example, let's say we have a dollar and want to buy 9 candies priced 10 cents each. How much change should we get ? According to Java (using the following code to calculate):
System.out.println(1.00 - 9 * .10);
We'll end up with $0.09999999999999998

This is certainly not the right number - and that problem accompanies us when writing the Salary Raiser.

Let's examing an intuitive attempt at the problem:

package ex5;
 
public class SalaryRaiser {
	private float salary;
 
	public static final float MAX_SALARY = 6000;
 
	public void raise() {
		if ( this.salary * 1.1 <= SalaryRaiser.MAX_SALARY) {
			this.salary *= 1.1;
		}
	}
 
	public SalaryRaiser() {
		this.salary = (float) ((Math.random() * 1000) + 5000);
	}
 
	public float getSalary() {
		return this.salary;
	}
}
package ex5;
import junit.framework.TestCase;
 
import org.junit.Assert;
 
public class SalaryRaiserTester extends TestCase {
 
	public void testRaise() {
		SalaryRaiser r = new SalaryRaiser();
		float oldSal = r.getSalary();
		System.out.println("Salary before raise = " + oldSal);
		r.raise();
 
		float newSal = r.getSalary();
		System.out.println("Salary after raise = " + newSal);
 
		Assert.assertTrue( r.getSalary() < SalaryRaiser.MAX_SALARY );
 
		if ( oldSal != newSal ) {
			Assert.assertTrue( oldSal * 1.1 == newSal );
		} else {
			Assert.assertTrue( oldSal * 1.1 > SalaryRaiser.MAX_SALARY );
		}
	}
}

The test fails at line 20 because of errors in the calculation. Java gives us two ways to deal with this situation. The first is using BigDecimal, and the second using long for money calculations. I'll demonstrate the second:

package ex5;
 
public class SalaryRaiserGood {
	private long salary;
 
	public static final long MAX_SALARY = 600000;
 
	public void raise() {
		long newsal = (long) (this.salary * 110 / 100);
		if ( newsal <= SalaryRaiserGood.MAX_SALARY) {
			this.salary = newsal;
		}
	}
 
	public SalaryRaiserGood() {
		this.salary = (long) ((Math.random() * 100000) + 500000);
	}
 
	public long getSalary() {
		return this.salary;
	}
}
package ex5;
 
import junit.framework.TestCase;
 
import org.junit.Assert;
 
public class SalaryRaiserGoodTest extends TestCase {
	public void testRaiseGood() {
		SalaryRaiserGood r = new SalaryRaiserGood();
		long oldSal = r.getSalary();
		System.out.println("Salary before raise = " + ((float) oldSal / 100));
		r.raise();
 
		long newSal = r.getSalary();
		System.out.println("Salary after raise = " + ((float) newSal / 100) );
 
		Assert.assertTrue( r.getSalary() < SalaryRaiserGood.MAX_SALARY );
 
		if ( oldSal != newSal ) {
			Assert.assertTrue( (oldSal * 110 / 100) == newSal );
		} else {
			Assert.assertTrue( (oldSal * 110 / 100) > SalaryRaiserGood.MAX_SALARY );
		}		
	}
}
 
package ex6;
 
public class Ex6_1 {
 
	public static void main(String [] args) {
		int n = (int) ( Math.random() * 50 );
 
		System.out.println("Looping until " + n);
 
		for ( int i=1; i <= n; i++ ) {
			System.out.println(i);
		}
	}
}
package ex6;
 
public class Ex6_7 {
 
	private int n;
 
	public Ex6_7(int n) {
		this.n = n;
	}
 
	/**
	 * Calculating the factorial value of n
	 * @return
	 */
	public int getFactorial() {
		int fact = 1;
 
		for ( int i=1; i <= n; i++ ) {
			fact *= i;
		}
 
		return fact;
	}
}
 
package ex6;
 
import org.junit.Assert;
import junit.framework.TestCase;
 
public class Ex6_7_Test extends TestCase {
 
	public void testFact() {
		Ex6_7 f3 = new Ex6_7(3);
		Ex6_7 f4 = new Ex6_7(4);
		Ex6_7 f10 = new Ex6_7(10);
		Ex6_7 f0 = new Ex6_7(0);
		Ex6_7 fminus5 = new Ex6_7(-5);
 
		Assert.assertEquals(f3.getFactorial(), 6);
		Assert.assertEquals(f4.getFactorial(), 24);
		Assert.assertEquals(f10.getFactorial(), 3628800);
		Assert.assertEquals(f0.getFactorial(), 1);
		Assert.assertEquals(fminus5.getFactorial(), 1);
	}
}
 
package Ex7;
 
/**
 * The Reverser class takes an array of values and reverses it
 */
public class Reverser {
	// note the use of package scope to ease up testing
	int [] values;
 
	public Reverser(int [] values) {
		this.values = values;
	}
 
	/**
	 * Reverses its internal list of values
	 * in place, by swapping values
	 */
	public void reverse() {
		int top = this.values.length - 1;
 
		for ( int i=0; i < (this.values.length / 2); i++ ) {
			int temp = this.values[i];
			this.values[i] = this.values[top - i];
			this.values[top - i] = temp;
		}
	}
 
	/**
	 * Prints the internal list of values
	 * on screen
	 */
	public void printValues() {
		for ( int i=0; i < this.values.length; i++ ) {
			System.out.println(this.values[i]);
		}
	}
}

package Ex7;
import junit.framework.TestCase;
 
import org.junit.Assert;
 
/**
 * The ReverserTest includes two tests. One for testing
 * the reverser class on Even length lists, and the 
 * other for Odd length list. We use assertArrayEquals
 * and two predefined value lists to find out if the reversing 
 * worked
 */
public class ReverserTest extends TestCase {
 
	public void testReverserEven() {
		int [] values = { 5, 7, 2, 4, 8, 6 };
		int [] rev    = { 6, 8, 4, 2, 7, 5 };
 
		Reverser r = new Reverser( values );
 
		r.printValues();
 
		Assert.assertArrayEquals(values, r.values);	
		r.reverse();
		Assert.assertArrayEquals(rev, r.values);
		r.printValues();
	}
 
	public void testReverserOdd() {
		int [] values = { 10, 20, 30, 40, 50 };
		int [] rev    = { 50, 40, 30, 20, 10 };
 
		Reverser r = new Reverser( values );
 
		r.printValues();
 
		Assert.assertArrayEquals(values, r.values);	
		r.reverse();
		Assert.assertArrayEquals(rev, r.values);
		r.printValues();
 
	}
}
 
public class Dups {
	private int [] arr;
 
	public boolean isElementInArray(int element, int [] array, int end_idx) {
		for ( int i=0; i < end_idx; i++ ) {
			if ( array[i] == element ) {
				return true;
			}
		}
 
		return false;
	}
 
	public void removeDups() {
		int [] unique = new int[arr.length];
		int num_uniques = 0;
 
		for ( int i=0; i < arr.length; i++) {
			if ( ! isElementInArray(arr[i], unique, num_uniques)) {
				unique[num_uniques] = arr[i];
				++num_uniques;
			}
		}
		int [] newarr = new int[num_uniques];
		System.arraycopy(unique, 0, newarr, 0, num_uniques);
		this.arr = newarr;
	}
 
	public Dups(int [] arr) {
		this.arr = arr;
	}
 
	public static void main(String [] args) {
		int [] arr = {1, 2, 2, 3, 4, 2, 8, 10, 8, 5 };
		Dups d = new Dups(arr);
		d.removeDups();
 
		for ( int x : d.arr ) {
			System.out.print(x + ", ");
		}
 
	}
}
course: