<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<HTML>
<HEAD>
<META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<META NAME="Generator" CONTENT="MS Exchange Server version 5.5.2654.45">
<TITLE>prePEP: Money data type</TITLE>
</HEAD>
<BODY>

<P><FONT SIZE=2>Here I send it.</FONT>
</P>

<P><FONT SIZE=2>Suggestions and all kinds of recomendations are more than welcomed.</FONT>
</P>

<P><FONT SIZE=2>If it all goes ok, it'll be a PEP when I finish writing the code.</FONT>
</P>

<P><FONT SIZE=2>Thank you.</FONT>
</P>

<P><FONT SIZE=2>.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Facundo</FONT>
</P>
<BR>

<P><FONT SIZE=2>------------------------------------------------------------------------</FONT>
</P>

<P><FONT SIZE=2>PEP: XXXX</FONT>
<BR><FONT SIZE=2>Title: Money data type</FONT>
<BR><FONT SIZE=2>Version: $Revision: 0.1 $</FONT>
<BR><FONT SIZE=2>Last-Modified: $Date: 2003/10/17 17:34:00 $</FONT>
<BR><FONT SIZE=2>Author: Facundo Batista &lt;fbatista@unifon.com.ar&gt;</FONT>
<BR><FONT SIZE=2>Status: Draft</FONT>
<BR><FONT SIZE=2>Type: Standards Track</FONT>
<BR><FONT SIZE=2>Content-Type: text/x-rst</FONT>
<BR><FONT SIZE=2>Created: 17-Oct-2003</FONT>
<BR><FONT SIZE=2>Python-Version: 2.3.3</FONT>
</P>
<BR>

<P><FONT SIZE=2>Abstract</FONT>
<BR><FONT SIZE=2>========</FONT>
</P>

<P><FONT SIZE=2>The idea is to make a Money data type, basically for financial uses, where</FONT>
<BR><FONT SIZE=2>decimals are needed but floating point is too inexact.&nbsp; The Money data type</FONT>
<BR><FONT SIZE=2>should support the Python standard functions and operations.</FONT>
</P>
<BR>

<P><FONT SIZE=2>Rationale</FONT>
<BR><FONT SIZE=2>=========</FONT>
</P>

<P><FONT SIZE=2>The detail of the requeriments are in the `Requirements`_ section.&nbsp; Here I'll</FONT>
<BR><FONT SIZE=2>include all the decisions made and why, and all the subjects still in</FONT>
<BR><FONT SIZE=2>discussion.&nbsp; The requirements will be numbered, to simplify discussion on</FONT>
<BR><FONT SIZE=2>each point.</FONT>
</P>

<P><FONT SIZE=2>As an XP exercise, I'll write the test cases before de class itself, so it'll</FONT>
<BR><FONT SIZE=2>comply exactly the requeriments of those tests.&nbsp; Please see them for an exact</FONT>
<BR><FONT SIZE=2>specification (and if you propose a different behaviour, please propose the</FONT>
<BR><FONT SIZE=2>corresponding test case if possible, thanks).</FONT>
</P>
<BR>

<P><FONT SIZE=2>Why Not To Use Tim Peters' FixedPoint?</FONT>
<BR><FONT SIZE=2>--------------------------------------</FONT>
</P>

<P><FONT SIZE=2>As we'll see in Requeriments, thera are items that FixedPoint doesn´t comply</FONT>
<BR><FONT SIZE=2>(because doesn't do something or does it different).&nbsp; It could be extended or</FONT>
<BR><FONT SIZE=2>modified to comply the Requeriments, but some needs are own to currency, and</FONT>
<BR><FONT SIZE=2>some features of FixedPoint are too much for Money, so taking them out will</FONT>
<BR><FONT SIZE=2>make this class simplier.</FONT>
</P>

<P><FONT SIZE=2>Anyway, sometime maybe one could be made subclass of the other, or just make</FONT>
<BR><FONT SIZE=2>one from both.&nbsp; The code of the Money class is based in large part on the</FONT>
<BR><FONT SIZE=2>code of Tim Peters' FixedPoint: thank you for your (very) valuable ideas.</FONT>
</P>
<BR>

<P><FONT SIZE=2>Items In Discussion</FONT>
<BR><FONT SIZE=2>-------------------</FONT>
</P>

<P><FONT SIZE=2>6. About repr(). Should ``myMoney == eval(repr(myMoney))``?</FONT>
</P>
<BR>

<P><FONT SIZE=2>Requirements</FONT>
<BR><FONT SIZE=2>============</FONT>
</P>

<P><FONT SIZE=2>1. The sintaxis should be ``Money(value, [precision])``.</FONT>
</P>

<P><FONT SIZE=2>2. The value could of the type:</FONT>
</P>

<P><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - another money (if you don't include *precision*, it get inheritated)</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - int or long (default *precision*: 0)::</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Money(45): 45</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Money(45, 2): 45.00</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Money(5000000000,3): 5000000000.000</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - float (*precision* must be included)::</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Money(50.33, 3): 50.330</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - string (*precision* get extracted from the string)::</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Money('25.32'): 25.32</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Money('25.32', 4): 25.3200</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - something that could be coerced by long() or float()</FONT>
</P>

<P><FONT SIZE=2>3. Not to support strings with engineer notation (you don't need this when</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp; using money).</FONT>
</P>

<P><FONT SIZE=2>4. Precision must be a non negative integer, and after created the object</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp; you could not change it.</FONT>
</P>

<P><FONT SIZE=2>5. Attributes ``decimalSeparator``, ``currencySymbol`` and</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp; ``thousandSeparator`` could be overloaded, just to easy change them</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp; subclassing. This same *decimalSeparator* is that used by the constructor</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp; when receives a string. Defaults are::</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp; </FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; decimalSeparator = '.'</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; currencySimbol = '$'</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; thousandSeparator = ''</FONT>
</P>

<P><FONT SIZE=2>6. Calling repr() should not return str(self), because if the subclass</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp; indicates that ``decimalSeparator=''``, this could carry to a confusion.</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp; So, repr() should show a tuple of three values: IntPart, FracPart,</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp; Precision.</FONT>
</P>

<P><FONT SIZE=2>7. To comply the test case of Mark McEahern::</FONT>
</P>

<P><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cost = Money('5.99')</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; percentDiscount = 10</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; months = 3</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; subTotal = cost * months</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; discount = subTotal * (percentDiscount * 1.0) / 100</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; total = subTotal - discount</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; assertEqual(total, Money('16.17'))</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp; </FONT>
<BR><FONT SIZE=2>8. To support the basic aritmetic (``+, -, *, /, //, **, %, divmod``) and the</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp; comparisons (``==, !=, &lt;, &gt;, &lt;=, &gt;=, cmp``) in the following cases:</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp; </FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Money op Money</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Money op otherType</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - otherType op Money</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - Money op= otherType</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp; </FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp; OtherType could be int, float or long. Automaticlly will be converted to</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp; Money, inheritating the precision from the other component of the</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp; operation (and, in the case of the float, maybe losing precision **before**</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp; the operation).</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp; </FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp; When both are Moneys, the result has the larger precision from both.</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp; </FONT>
<BR><FONT SIZE=2>9. To support unary operators (``-, +, abs``).</FONT>
</P>

<P><FONT SIZE=2>10. To support the built-in methods:</FONT>
</P>

<P><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - min, max</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - float, int, long (int and long are rounded by Money)</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - str, repr</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - hash</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - copy, deepcopy</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - bool (0 is false, otherwise true)</FONT>
</P>

<P><FONT SIZE=2>11. To have methods that return its components. The value of Money will be</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp; ``(int part) + (frac part) / (10 ** precision)``.</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp; </FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - ``getPrecision()``: the precision</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - ``getFracPart()``: the fractional part (as long)</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; - ``getIntPart()``: the int part (as long)</FONT>
</P>

<P><FONT SIZE=2>12. The rounding to be financial. This means that to round a number in a</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp; position, if the digit at the right of that position is bigger than 5,</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp; the digit at the left of that position is incremented by one, if it's</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp; smaller than 5 isn't::</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp; </FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.123 --&gt; 1.12</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.128 --&gt; 1.13</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp; </FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp; But when the digit at the right of that position is ==5. There, if the</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp; digit at the left of that position is odd, it gets incremented, otherwise</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp; isn't::</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp; </FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.125 --&gt; 1.12</FONT>
<BR><FONT SIZE=2>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1.135 --&gt; 1.14</FONT>
</P>
<BR>

<P><FONT SIZE=2>Reference Implementation</FONT>
<BR><FONT SIZE=2>========================</FONT>
</P>

<P><FONT SIZE=2>To be included later:</FONT>
</P>

<P>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>- code</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>- test code</FONT>
<BR>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <FONT SIZE=2>- documentation</FONT>
</P>
<BR>

<P><FONT SIZE=2>Copyright</FONT>
<BR><FONT SIZE=2>=========</FONT>
</P>

<P><FONT SIZE=2>This document has been placed in the public domain.</FONT>
</P>
<BR>
<BR>
<BR>
<BR>

<P><B><FONT SIZE=2>. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .</FONT></B></P>

<P><B><U><FONT SIZE=2>ADVERTENCIA&nbsp;</FONT></U> </B>
</P>

<P><B><FONT SIZE=2>La información contenida en este mensaje y cualquier archivo anexo al mismo, son para uso exclusivo del destinatario y pueden contener información confidencial o propietaria, cuya divulgación es sancionada por la ley. </FONT></B></P>

<P><B><FONT SIZE=2>Si Ud. No es uno de los destinatarios consignados o la persona responsable de hacer llegar este mensaje a los destinatarios consignados, no está autorizado a divulgar, copiar, distribuir o retener información (o parte de ella) contenida en este mensaje. Por favor notifíquenos respondiendo al remitente, borre el mensaje original y borre las copias (impresas o grabadas en cualquier medio magnético) que pueda haber realizado del mismo. </FONT></B></P>

<P><B><FONT SIZE=2>Todas las opiniones contenidas en este mail son propias del autor del mensaje y no necesariamente coinciden con las de Telefónica Comunicaciones Personales S.A. o alguna empresa asociada. </FONT></B></P>

<P><B><FONT SIZE=2>Los mensajes electrónicos pueden ser alterados, motivo por el cual Telefónica Comunicaciones Personales S.A. no aceptará ninguna obligación cualquiera sea el resultante de este mensaje. </FONT></B></P>

<P><B><FONT SIZE=2>Muchas Gracias.</FONT></B>
</P>

</BODY>
</HTML>