/* * Extended Static Checking Exercise * Fall 2013 CSCI181F - Verification-centric Software Engineering * Daniel M. Zimmerman */ //package annotated; /** * A class that represents a quantity of (U.S.) cash in dollars * and cents. The quantity can be positive or negative (representing * an asset or a debt). Instances of this class are immutable, so it has * only queries (and a constructor). * * @author Daniel M. Zimmerman * @version 2013-10-17 */ /*@ code_java_math */ public class CashAmountOnlyPrivate { // invariants for sane amounts of dollars and cents //@ public invariant -CENTS_IN_DOLLAR < my_cents && my_cents < CENTS_IN_DOLLAR; //@ public invariant !(my_cents > 0 && my_dollars < 0); //@ public invariant !(my_cents < 0 && my_dollars > 0); /** * The number of cents in one dollar. */ public static final int CENTS_IN_DOLLAR = 100; /** * The number of dollars. */ private /*@ spec_public */ final int my_dollars; /** * The number of cents. */ private /*@ spec_public */ final int my_cents; //@ requires -100 < the_cents && the_cents < 100; //@ requires !(the_cents > 0 && the_dollars < 0); //@ requires !(the_cents < 0 && the_dollars > 0); //@ ensures my_dollars == the_dollars && my_cents == the_cents; /** * Constructs a new CashAmount representing the specified amount of cash. * * @param the_dollars The number of dollars. * @param the_cents The number of cents. */ public CashAmountOnlyPrivate(final int the_dollars, final int the_cents) { my_dollars = the_dollars; my_cents = the_cents; } /** * @return a new CashAmount representing the negation of this * CashAmount. */ public CashAmountOnlyPrivate negate() { return new CashAmountOnlyPrivate(-my_dollars, -my_cents); } /*@ ensures \result.my_dollars * CENTS_IN_DOLLAR + \result.my_cents == the_amount.my_dollars * CENTS_IN_DOLLAR + the_amount.my_cents + my_dollars * CENTS_IN_DOLLAR + my_cents; */ /** * Increases this CashAmount by the specified CashAmount. * * @param the_amount The amount to increase by. * @return The resulting CashAmount. */ public CashAmountOnlyPrivate increase(final CashAmountOnlyPrivate the_amount) { int new_dollars = my_dollars + the_amount.my_dollars; int new_cents = my_cents + the_amount.my_cents; if (new_cents <= -CENTS_IN_DOLLAR) { new_cents = new_cents + CENTS_IN_DOLLAR; new_dollars = new_dollars - 1; } if (new_cents >= CENTS_IN_DOLLAR) { new_cents = new_cents - CENTS_IN_DOLLAR; new_dollars = new_dollars + 1; } if (new_cents < 0 && new_dollars > 0) { new_cents = new_cents + CENTS_IN_DOLLAR; new_dollars = new_dollars - 1; } if (new_cents > 0 && new_dollars < 0) { new_cents = new_cents - CENTS_IN_DOLLAR; new_dollars = new_dollars + 1; } return new CashAmountOnlyPrivate(new_dollars, new_cents); } /** * Decreases this CashAmount by the specified CashAmount. * * @param the_amount The amount to decrease by. * @return The resulting CashAmount. */ public CashAmountOnlyPrivate decrease(final CashAmountOnlyPrivate the_amount) { return increase(the_amount.negate()); } /** * @return The number of dollars in this CashAmount. */ //@ ensures \result == my_dollars; public /*@ pure helper */ int dollars() { return my_dollars; } /** * @return The number of cents in this CashAmount. */ //@ ensures \result == my_cents; public /*@ pure helper */ int cents() { return my_cents; } /*@ ensures \result <==> the_other.my_dollars == my_dollars && the_other.my_cents == my_cents; */ /** * Compare this CashAmount with the specified CashAmount for being identical. * Being identical here means "has exactly the same numbers of dollars and cents." * * @param the_other The other CashAmount. * @return true if the two amounts are identical, false otherwise. */ public /*@ pure helper */ boolean identical(final CashAmountOnlyPrivate the_other) { return the_other.my_dollars == my_dollars && the_other.my_cents == my_cents; } /*@ ensures \result <==> the_other.my_dollars * CENTS_IN_DOLLAR + the_other.my_cents == my_dollars * CENTS_IN_DOLLAR + my_cents; */ /** * Compare this CashAmount with the specified CashAmount for equivalence. * Equivalent here means "represents the same total number of cents". * * @param the_other The other CashAmount. * @return true if the two amounts are equivalent, false otherwise. */ public /*@ pure helper */ boolean equivalent(final CashAmountOnlyPrivate the_other) { return the_other.my_dollars * CENTS_IN_DOLLAR + the_other.my_cents == my_dollars * CENTS_IN_DOLLAR + my_cents; } }