<!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>. 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 <fbatista@unifon.com.ar></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. 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. 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. 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. 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). 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. 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> - another money (if you don't include *precision*, it get inheritated)</FONT>
<BR><FONT SIZE=2> </FONT>
<BR><FONT SIZE=2> - int or long (default *precision*: 0)::</FONT>
<BR><FONT SIZE=2> </FONT>
<BR><FONT SIZE=2> Money(45): 45</FONT>
<BR><FONT SIZE=2> Money(45, 2): 45.00</FONT>
<BR><FONT SIZE=2> Money(5000000000,3): 5000000000.000</FONT>
<BR><FONT SIZE=2> </FONT>
<BR><FONT SIZE=2> - float (*precision* must be included)::</FONT>
<BR><FONT SIZE=2> </FONT>
<BR><FONT SIZE=2> Money(50.33, 3): 50.330</FONT>
<BR><FONT SIZE=2> </FONT>
<BR><FONT SIZE=2> - string (*precision* get extracted from the string)::</FONT>
<BR><FONT SIZE=2> </FONT>
<BR><FONT SIZE=2> Money('25.32'): 25.32</FONT>
<BR><FONT SIZE=2> Money('25.32', 4): 25.3200</FONT>
<BR><FONT SIZE=2> </FONT>
<BR><FONT SIZE=2> - 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> 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> you could not change it.</FONT>
</P>
<P><FONT SIZE=2>5. Attributes ``decimalSeparator``, ``currencySymbol`` and</FONT>
<BR><FONT SIZE=2> ``thousandSeparator`` could be overloaded, just to easy change them</FONT>
<BR><FONT SIZE=2> subclassing. This same *decimalSeparator* is that used by the constructor</FONT>
<BR><FONT SIZE=2> when receives a string. Defaults are::</FONT>
<BR><FONT SIZE=2> </FONT>
<BR><FONT SIZE=2> decimalSeparator = '.'</FONT>
<BR><FONT SIZE=2> currencySimbol = '$'</FONT>
<BR><FONT SIZE=2> thousandSeparator = ''</FONT>
</P>
<P><FONT SIZE=2>6. Calling repr() should not return str(self), because if the subclass</FONT>
<BR><FONT SIZE=2> indicates that ``decimalSeparator=''``, this could carry to a confusion.</FONT>
<BR><FONT SIZE=2> So, repr() should show a tuple of three values: IntPart, FracPart,</FONT>
<BR><FONT SIZE=2> Precision.</FONT>
</P>
<P><FONT SIZE=2>7. To comply the test case of Mark McEahern::</FONT>
</P>
<P><FONT SIZE=2> cost = Money('5.99')</FONT>
<BR><FONT SIZE=2> percentDiscount = 10</FONT>
<BR><FONT SIZE=2> months = 3</FONT>
<BR><FONT SIZE=2> subTotal = cost * months</FONT>
<BR><FONT SIZE=2> discount = subTotal * (percentDiscount * 1.0) / 100</FONT>
<BR><FONT SIZE=2> total = subTotal - discount</FONT>
<BR><FONT SIZE=2> assertEqual(total, Money('16.17'))</FONT>
<BR><FONT SIZE=2> </FONT>
<BR><FONT SIZE=2>8. To support the basic aritmetic (``+, -, *, /, //, **, %, divmod``) and the</FONT>
<BR><FONT SIZE=2> comparisons (``==, !=, <, >, <=, >=, cmp``) in the following cases:</FONT>
<BR><FONT SIZE=2> </FONT>
<BR><FONT SIZE=2> - Money op Money</FONT>
<BR><FONT SIZE=2> - Money op otherType</FONT>
<BR><FONT SIZE=2> - otherType op Money</FONT>
<BR><FONT SIZE=2> - Money op= otherType</FONT>
<BR><FONT SIZE=2> </FONT>
<BR><FONT SIZE=2> OtherType could be int, float or long. Automaticlly will be converted to</FONT>
<BR><FONT SIZE=2> Money, inheritating the precision from the other component of the</FONT>
<BR><FONT SIZE=2> operation (and, in the case of the float, maybe losing precision **before**</FONT>
<BR><FONT SIZE=2> the operation).</FONT>
<BR><FONT SIZE=2> </FONT>
<BR><FONT SIZE=2> When both are Moneys, the result has the larger precision from both.</FONT>
<BR><FONT SIZE=2> </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> - min, max</FONT>
<BR><FONT SIZE=2> - float, int, long (int and long are rounded by Money)</FONT>
<BR><FONT SIZE=2> - str, repr</FONT>
<BR><FONT SIZE=2> - hash</FONT>
<BR><FONT SIZE=2> - copy, deepcopy</FONT>
<BR><FONT SIZE=2> - 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> ``(int part) + (frac part) / (10 ** precision)``.</FONT>
<BR><FONT SIZE=2> </FONT>
<BR><FONT SIZE=2> - ``getPrecision()``: the precision</FONT>
<BR><FONT SIZE=2> - ``getFracPart()``: the fractional part (as long)</FONT>
<BR><FONT SIZE=2> - ``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> position, if the digit at the right of that position is bigger than 5,</FONT>
<BR><FONT SIZE=2> the digit at the left of that position is incremented by one, if it's</FONT>
<BR><FONT SIZE=2> smaller than 5 isn't::</FONT>
<BR><FONT SIZE=2> </FONT>
<BR><FONT SIZE=2> 1.123 --> 1.12</FONT>
<BR><FONT SIZE=2> 1.128 --> 1.13</FONT>
<BR><FONT SIZE=2> </FONT>
<BR><FONT SIZE=2> But when the digit at the right of that position is ==5. There, if the</FONT>
<BR><FONT SIZE=2> digit at the left of that position is odd, it gets incremented, otherwise</FONT>
<BR><FONT SIZE=2> isn't::</FONT>
<BR><FONT SIZE=2> </FONT>
<BR><FONT SIZE=2> 1.125 --> 1.12</FONT>
<BR><FONT SIZE=2> 1.135 --> 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> <FONT SIZE=2>- code</FONT>
<BR> <FONT SIZE=2>- test code</FONT>
<BR> <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 </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>