Tipo de dato Money

Batista, Facundo FBatista en uniFON.com.ar
Jue Oct 16 19:57:16 CEST 2003


Introducción
------------

La idea es hacer un tipo de datos Money, basicamente para usos financieros,
donde se necesitan decimales pero el punto flotante es demasiado inexacto.
El tipo Money deberá soportar las funciones y operaciones estándares a
Python.

Como ejercicio de XP, escribiré los casos de prueba antes de la clase
propiamente dicha, luego la dejaré en SourceForge junto con el resto de los
datos.

Sería interesante (y útil) que esta clase pase a formar parte de la
biblioteca estándar, falta verificar que condiciones debe cumplir para poder
hacerlo.

Este código es de dominio público. En los módulos, asigné el copyright a
PSF, falta verificar si hay que solicitar algo previamente.

Por favor, siéntanse libres de realizar cualquier sugerencia. Gracias.


¿Por qué no usar FixedPoint de Tim Peters?
------------------------------------------

Como veremos en Requerimientos, hay puntos que FixedPoint no cumple (porque
no hace algo o lo hace distinto).

Se podría extender o modificar dicha clase para cumplir los Requerimientos,
pero algunas necesidades son propias de la moneda, y algunas características
de FixedPoint son demasiado para Money, lo que al sacarlas harán más simples
a esta clase.

De cualquier manera, en algún momento quizás se pueda hacer que una sea
subclase de la otra, o simplemente hacer una de ambas.

El código de la clase Money está basado en gran parte en el de FixedPoint de
Tim Peters: gracias por tus (muy) valiosas ideas. 


Requerimientos
--------------

La sintaxis debe ser Money(valor, [precision]).

El valor puede ser de tipo:
	- otro money (si no se incluye *precision*, la hereda)
	- int o long (*precision* default: 0)
		Money(45): 45
		Money(45, 2): 45.00
		Money(5000000000,3): 5000000000.000
	- float (*precision* pasa a ser obligatoria)
		Money(50.33, 3): 50.330
	- string (*precision* se extrae de la cadena).
		Money('25.32'): 25.32
		Money('25.32', 4): 25.3200
	- algo convertible por long() o float()

No se soportarán strings con notación ingenieril, ya que al hablar de dinero
esto no se necesita. 
	
La precisión debe ser un entero no negativo, y no podrá cambiarse luego de
creado el objeto.

Se debe poder sobrecargar decimalSeparator y currencySymbol, para que se
pueda cambiar facilmente haciendo una subclase. Ese mismo decimalSeparator
es el que usa el constructor al recibir una string. Los default son:
decimalSeparator = '.', currencySymbol = '$'. 

Llamar a repr() no debe devolver str(self), ya que si la subclase indicar
que decimalSeparator='', lleva a una confusión. Por lo tanto, repr() debe
mostrar una tupla de tres valores: IntPart, FracPart, Precision.

Que cumpla el caso de prueba de Mark McEahern:
	cost = Money('5.99')
	percentDiscount = 10
	months = 3
	subTotal = cost * months
	discount = subTotal * (percentDiscount * 1.0) / 100
	total = subTotal - discount
	assertEqual(total, Money('16.17'))
	
Que soporte la aritmética básica (+, -, *, /, //, **, %, divmod) y las
comparaciones (==, !=, <, >, <=, >=, cmp) en los siguientes casos:
	- Money op Money
	- Money op otherType
	- otherType op Money
	- Money op= otherType
	- Nota 1: OtherType puede ser int, float o long. Automáticamente se
convertirá a Money, heredando la precision del otro componente de la
operación (y por lo tanto, en el caso del float, posiblemente perdiendo
precisión **antes** de la operación).
	- Nota 2: Cuando ambos son Money, el resultado tiene la mayor
precisión de los dos.
	
Que soporte los operadores unarios (-, +, abs).

Que soporte los métodos bult-in:
	- min, max
	- float, int, long (int y long son redondeados por Money).
	- str, repr
	- hash
	- copy, deepcopy

Que se pueda:
	- usar como clave en dict
	- usar como booleano
	- hacer un pickle
	
Que tenga métodos que devuelvan sus componentes:
	- getPrecision: la precisión
	- getFracPart: la parte fraccional (como un long)
	- getIntPart: la parte entera (como un long)
	- debe cumplir que el valor de Money sea (parte entera) + (parte
fraccional) / (10 ** precision)

Que el redondeo sea el financiero (ejemplo redondeando a dos deciamles):
	a b , c d e f ...
	--------- ----...
	    x      y
	se incrementará d si (y > 50000...) o (y == 50000... y d es impar)


Facundo Batista
Gestión de Red
fbatista en unifon.com.ar
(54 11) 5130-4643
Cel: 15 5132 0132







. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
. . . . . . . . . . . . . . .
ADVERTENCIA  

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. 

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. 

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. 

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. 

Muchas Gracias.
------------ próxima parte ------------
Se ha borrado un adjunto en formato HTML...
URL: <http://mail.python.org/pipermail/python-es/attachments/20031016/e779c5f3/attachment.html>
------------ próxima parte ------------
_______________________________________________
Python-es mailing list
Python-es en aditel.org
http://listas.aditel.org/listinfo/python-es


Más información sobre la lista de distribución Python-es