/* * @(#)Natural.java * */ /** * A natural number is a non-negative integer. All operations behave * like Java's primitive integer types. Natural provides analogues to most of * Java's primitive integer operators, and most relevant methods from java.lang.Math. * Additionally, Natural provides operations for modular arithmetic. *

* Semantics of arithmetic operations exactly mimic those of Java's integer * arithmetic operators, as defined in The Java Language Specification. * For example, division by zero throws an ArithmeticException, and * division of a negative by a positive yields a negative (or zero) remainder. *

* Comparison operations perform signed integer comparisons, analogous to * those performed by Java's relational and equality operators. *

* For the sake of brevity and clarity, pseudo-code is used throughout the * descriptions of Natural methods. The pseudo-code expression * (i + j) is shorthand for "a Natural whose value is * that of the Natural i plus that of the Natural j." * The pseudo-code expression (i == j) is shorthand for * "true if and only if the Natural i represents the same * value as the the Natural j." Other pseudo-code expressions are * interpreted similarly. * * @author John Dalbey, edited by Sean Dinsmore, Thomas Bouldin * @version 1.5 3/20/2006 * Enhanced to include a maxvalue. * 3/9/05 modified equals() to not consider maxvalue. * 3/12/05 removed named constants zero and one. * 3/20/06 added compareTo(int) method. */ import java.util.StringTokenizer; import java.lang.Character; import java.lang.Math; public class Natural implements Comparable { /** * The implementation of Natural */ private int value; private int MAXVALUE; //Constructors /** * Translates the decimal String representation of a Natural into a * Natural. The String representation consists of an optional minus * sign followed by a sequence of one or more decimal digits. The * character-to-digit mapping is provided by Character.digit. * The String may not contain any extraneous characters (whitespace, for * example). * * @param val decimal String representation of Natural. * @throws NumberFormatException val is not a valid representation * of a Natural. * @see Character#digit */ public Natural(String val) { StringTokenizer tokenizer = new StringTokenizer(val," "); if (tokenizer.countTokens() > 1) { throw new NumberFormatException(); } if (val.charAt(0) == '-') { val = val.substring(1,val.length()); } value = 0; for (int i=0; ival is negative */ public Natural(int val) { if (val < 0) { throw new NumberFormatException(); } value = val; MAXVALUE = -1; } /** * Constructs a Natural with the specified int value and maximum. * * @param val int representation of Natural. * @param max int value that is the max this number can take. * @throws NumberFormatException if val is negative * @throws NumberFormatException if max is negative */ public Natural(int val, int max) { if (val < 0 || max < 0) { throw new NumberFormatException(); } value = val; MAXVALUE = max; } // Arithmetic Operations /** * Returns a Natural whose value is (this + val). * * @param val value to be added to this Natural. * @return this + val */ public Natural add (Natural val) { if( value + val.intValue() > MAXVALUE && MAXVALUE != -1) throw new ArithmeticException(); Natural answer = new Natural(val.intValue() + value); answer.MAXVALUE = MAXVALUE; return answer; } /** * Adds one to this Natural. * @throws ArithmeticException() if this natural has a maximum value * and the result of incrementing exceeds the maximum value. * */ public void increment() { if (value + 1 > MAXVALUE && MAXVALUE != -1) throw new java.lang.ArithmeticException(); //OverflowException(); value = value + 1; } /** * Returns a Natural whose value is (this - val). * * @param val value to be subtracted from this Natural. * @return this - val * @throws ArithmeticException if result would be negative. */ public Natural subtract(Natural val) { if (value - val.value < 0) { throw new java.lang.ArithmeticException(); } else { Natural answer = new Natural( value - val.value); answer.MAXVALUE = MAXVALUE; return answer; } } /** * Subtracts one from this Natural. * @throws ArithmeticException if result would be negative. */ public void decrement() { if (value - 1 < 0) throw new ArithmeticException(); value = value - 1; } /** * Returns a Natural whose value is (this * val). * * @param val value to be multiplied by this Natural. * @return this * val */ public Natural multiply(Natural val) { if(MAXVALUE != -1 && value* val.intValue() > MAXVALUE) { throw new ArithmeticException(); } Natural answer = new Natural(value * val.intValue()); answer.MAXVALUE = MAXVALUE; return answer; } /** * Returns a Natural whose value is (this2). * * @return this2 */ public Natural square() { if(value*value > MAXVALUE && MAXVALUE != -1) throw new ArithmeticException(); Natural answer =new Natural(value * value); answer.MAXVALUE = MAXVALUE; return answer; } /** * Returns a Natural whose value is (this / val). * * @param val value by which this Natural is to be divided. * @return this / val * @throws ArithmeticException val==0 */ public Natural divide(Natural val) { if (val.intValue() == 0) { throw new ArithmeticException(); } Natural answer = new Natural(value / val.intValue()); answer.MAXVALUE = MAXVALUE; return answer; } /** * Returns a Natural whose value is (this % val). * * @param val value by which this Natural is to be divided, and the * remainder computed. * @return this % val * @throws ArithmeticException val==0 */ public Natural remainder(Natural val) { if (val.value == 0) { throw new ArithmeticException(); } // 3 line step to build and return the answer is not necessary here // because there is no MAXVALUE to set. (3 line method is otherwise // necessary because of the case where MAXVALUE = -1 return new Natural(value % val.intValue()); } /** * Returns a Natural whose value is (thisexponent). * Note that exponent is an integer rather than a Natural. * * @param exponent exponent to which this Natural is to be raised. * @return thisexponent * @throws ArithmeticException exponent is negative. (This would * cause the operation to yield a non-integer value.) */ public Natural pow(int exponent) { if (exponent < 0) { throw new ArithmeticException(); } if (exponent == 0) { Natural answer = new Natural(1); answer.MAXVALUE = MAXVALUE; return answer; } int temp = value; for (int i=1; i MAXVALUE && MAXVALUE != -1) throw new ArithmeticException(); Natural answer = new Natural(temp); answer.MAXVALUE = MAXVALUE; return answer; } // Comparison Operations /** * Compares this Natural with the specified Natural. This method is * provided in preference to individual methods for each of the six * boolean comparison operators (<, ==, >, >=, !=, <=). The * suggested idiom for performing these comparisons is: * (x.compareTo(y) <op> 0), * where <op> is one of the six comparison operators. * * @param val Natural to which this Natural is to be compared. * @return -1, 0 or 1 as this Natural is numerically less than, equal * to, or greater than val. */ public int compareTo(Natural val) { if (value < val.value) { return (-1); } if (value == val.value) { return 0; } return 1; } //end method compareTo /** * Compares this Natural with the specified integer. * * @param val int to which this Natural is to be compared. * @pre val >= 0 * @return -1, 0 or 1 as this Natural is numerically less than, equal * to, or greater than val. */ public int compareTo(int val) { Natural natval = new Natural(val); return this.compareTo(natval); } //end method compareTo /** * Same as compareTo() above, just taking an object as parameter. */ public int compareTo(Object x) { Natural temp = (Natural)(x); return this.compareTo(temp); } /** * Compares this Natural with the specified Object for equality. * * @param x Object to which this Natural is to be compared. * @return true if and only if the specified Object is a * Natural whose value is numerically equal to this Natural. */ public boolean equals(Object x) { if (x == null) return false; if (x.getClass() != getClass()) return false; Natural temp = (Natural)(x); return ( temp.value == value ); } /** * Returns the minimum of this Natural and val. * * @param val value with with the minimum is to be computed. * @return the Natural whose value is the lesser of this Natural and * val. If they are equal, either may be returned. */ public Natural min(Natural val) { Natural answer; if (value < val.value) { answer = new Natural(value); answer.MAXVALUE = MAXVALUE; } else { answer = new Natural(val.value); answer.MAXVALUE = val.MAXVALUE; } return answer; } /** * Returns the maximum of this Natural and val. * * @param val value with with the maximum is to be computed. * @return the Natural whose value is the greater of this and * val. If they are equal, either may be returned. */ public Natural max(Natural val) { Natural answer; if (value > val.value) { answer = new Natural(value); answer.MAXVALUE = MAXVALUE; } else { answer = new Natural(val.value); answer.MAXVALUE = val.MAXVALUE; } return answer; } /** * Returns the decimal String representation of this Natural. The * digit-to-character mapping provided by Character.forDigit is * used, and a minus sign is prepended if appropriate. (This * representation is compatible with the (String) constructor, and allows * for String concatenation with Java's + operator.) * * @return decimal String representation of this Natural. * @see Character#forDigit */ public String toString() { return String.valueOf(value); } /** * Converts this Natural to an int. * * @return this Natural converted to an int. */ public int intValue() { return value; } /** * Converts this Natural to a long. * * @return this Natural converted to a long. */ public long longValue() { return (long)(value); } /** * Converts this Natural to a float. * @return this Natural converted to a float. */ public float floatValue() { return (float)(value); } /** * Converts this Natural to a double. * * @return this Natural converted to a double. */ public double doubleValue() { return (double)(value); } /** * Returns the max value of the natural number (-1 means no max) * * @return

-1
if there is no max, otherwise the max */ public int getMax() { return MAXVALUE; } // for future use //class OverflowException extends Exception {} /** * A local test driver */ public static void main(String[] args) { Natural one = new Natural(2); Natural two = new Natural("4"); Natural sum = new Natural("9"); System.out.println("Unit test of Natural class."); System.out.println("First Natural: " + one + "\nSecond Natural: " + two); System.out.println("First + Second: " + one.add(two)); System.out.println("Second - First: " + two.subtract(one)); System.out.println("First * Second: " + one.multiply(two)); System.out.println("Second / First: " + two.divide(one)); System.out.println("First compareTo Second: " + one.compareTo(two)); System.out.println("First compareTo 0 (int) " + one.compareTo(0)); System.out.println("First compareTo 2 (int) " + one.compareTo(2)); System.out.println("First compareTo 5 (int) " + one.compareTo(5)); System.out.println("First compareTo Second (Object) " + one.compareTo((Object) two)); System.out.println("First equals Second?: " + one.equals(two)); System.out.println("First remainder() Second: " + one.remainder(two)); System.out.println("First Squared: " + one.square()); System.out.println("First^3: " + one.pow(3) + "\nSecond^4: " + two.pow(4)); System.out.println("First/Second min?: " + one.min(two)); System.out.println("First/Second max?: " + one.max(two)); one.increment(); System.out.println("First incremented: " + one); two.decrement(); System.out.println("Second decremented: " + two); // throw an exception Natural big = new Natural(1,2); System.out.println("try to exceed MAX: "); big.increment(); System.out.println("BIG = " + big); big.increment(); System.out.println("BIG = " + big); // throw an exception System.out.println("try to make a negative: " + one.subtract(new Natural(999))); } }