note description: "[ Efficient value type for handling money objects in dollars and cents, with precision and safety in plus and minus operators. See end of class for specification. ]" author: "JSO" date: "$Date$" revision: "$Revision$" expanded class interface MONEY create make, make_with_float, make_from_int, default_create feature -- public cents: INTEGER_64 amount: FLOAT -- float value of cents ensure Result = create {FLOAT}.make_from_real (cents / 100) feature --compare is_equal (other: like Current): BOOLEAN -- Is other attached to an object of the same type -- as current object and identical to it? is_less alias "<" (other: MONEY): BOOLEAN -- Is current money less than other? feature -- effect numeric plus alias "+" (other: MONEY): MONEY -- Sum with other safely require safe_to_do_plus: safe_plus (cents, other.cents) ensure correct: Result = (create {MONEY}.make_from_int (cents + other.cents)) minus alias "-" (other: MONEY): MONEY -- minus with other safely require safe_to_do_minus: safe_minus (cents, other.cents) ensure correct: Result = (create {MONEY}.make_from_int (cents - other.cents)) product alias "*" (arg: FLOAT): MONEY -- Product by arg ensure then Result = (create {MONEY}.make_with_float ((amount * arg))) one: like Current -- Neutral element for "*" and "/" zero: like Current -- Neutral element for "+" and "-" divisible (other: FLOAT): BOOLEAN -- May current object be divided by other? quotient alias "/" (other: FLOAT): MONEY -- Division by other require else other /= create {FLOAT}.make_from_real (0.0) identity alias "+": MONEY -- Unary plus opposite alias "-": MONEY -- Unary minus feature -- allocation allocated (arg: INTEGER_32): MONEY_ARRAY -- Divide by arg into equal amounts require comment ("Avoid division by zero and within range") arg_positive: arg > 0 and arg.to_integer_64 <= cents ensure Result.count = arg Result.sum = Current result_correct: across 1 |..| arg as j all (j.item.to_integer_64 <= cents \\ arg.to_integer_64 implies Result [j.item].cents = (cents // arg.to_integer_64) + 1) and (j.item.to_integer_64 > cents \\ arg.to_integer_64 implies Result [j.item].cents = (cents // arg.to_integer_64)) end allocated_by_ratios (ratios: NUM_ARRAY [INTEGER_32]): MONEY_ARRAY -- Divide according to ratios require ratios /= Void and then ratios.sum /= ratios.sum.zero ensure Result.count = ratios.count Result.sum = Current result_correct: across 1 |..| ratios.count as j all Result [j.item].cents = ((cents * ratios [j.item].to_integer_64) / ratios.sum.to_integer_64).floor.to_integer_64 or Result [j.item].cents = ((cents * ratios [j.item].to_integer_64) / ratios.sum.to_integer_64).floor + 1.to_integer_64 end feature -- out out: STRING_8 -- New string containing terse printable representation -- of current object comment (s: STRING_8): BOOLEAN invariant min: cents.Min_value = -9223372036854775808 max: cents.Max_value = 9223372036854775807 consistent_amount: amount = create {FLOAT}.make_from_real (cents / 100) note specification: "[ Efficient value type for handling money in dollars and cents. The class stores money as an INTEGER_64. MONEY values are within about 92,000 trillion dollars: $92,233,720,368,547,758.07 Min_value: INTEGER_64 = -9223372036854775808 Max_value: INTEGER_64 = 9223372036854775807 But the API works in terms of dollars and cents. Thus create {MONEY}.make(10,966)creates $10.966. Addition and subtraction are meaningful with type MONEY x MONEY -> MONEY. Addition and subtraction are precise within the stated range, and are protected with preconditions to stay safely within range without overflows. For product, we have only one choice: MONEY x SCALAR -> MONEY where scalar can be float or int; we have float. For quotient we have MONEY x SCALAR -> MONEY which tells us amount / number_of_people i.e. approximately the amount that each person gets dividing equally.Protected so that there is no division by zero. These signatures satisfy dimensional analysis constraints. As an alternative to the imprecise quotient (which can loose pennies), there are pecise allocation queries to divide money into equal amounts without loss. Class MONEY uses a new type FLOAT with approximately equal operators. Division and multiplication using float is imprecise. Feature 'out' displays money rounded to two decimal points. ]" end -- class MONEY
Generated by ISE EiffelStudio