On Tue, 15 Mar 2005, Jacob S. wrote:
> Okay, not a very descriptive subject, but here goes... > > This is the code Hi Jacob, > from decimal import Decimal as D Ok, I think I see why you're using this, but you have to be aware that the decimal module itself is susceptible to imprecision: http://www.python.org/doc/lib/decimal-notes.html so, even with the decimal module, we still run the potential for roundoff errors. I think you may be looking for something like a "rational" module. There's an unofficial one that comes with the Python source code, in the Demo/classes directory as 'rat.py'. Let me see if I can get a link to it... ok, here it is: http://cvs.sourceforge.net/viewcvs.py/*checkout*/python/python/dist/src/Demo/classes/Rat.py You may find this module more useful. I really hope something like this migrates into the Standard Library some day... *grin* Let's take a look at some other parts of the code. > dic = {## Metric ## > 'm':(lambda x:x,lambda x:x), > 'km':(lambda x:1000*x,lambda x:x/1000), > 'cm':(lambda x:x/100,lambda x:100*x), > 'mm':(lambda x:x/1000,lambda x:1000*x), The lambdas might be slightly scary to some folks. I'm usually for lambdas, but this seems a bit too much. *grin* Another way you can write this is just to store the constants. And, although the 'dic' above stores pairs of ratios, you might be able to live with just one of them. A table that stores a similar amount of information might be something like this: ### meterRatios = { 'm' : D(1), ## 1 meter == 1 meter 'km' : D(1000), ## 1000 meters == 1 kilometer 'cm' : D(1)/D(100), ## .001 meters == 1 centimeter 'mm' : D(1)/D(1000), ## .0001 meters == 1 millimeter } ### The reason this stores equivalent data is because it stores the ratio of one meter to the unit in question. I'm being perhaps a little too paranoid in building decimals by calling D() n both the numerator and denominator, but oh well. *grin* We can also do it without explicitely defining 'from meter' stuff, because the ratios that define going "to meters" and going "from meters" are inverses of each other. That is, from the table above, we can see that since there's one meter to a thousanth of a millimeter, we can go the other way and say that one thousand millimeters is one meter. (1/x) Here's one way to write a fromMeterToUnit function: ### def inverse(number): """Returns 1 / number.""" return D(1) / number def fromMeterToUnit(meters, unit): """Converts meters to a specific unit.""" return meters * inverse(meterRatios[unit]) ### Let's just double check to see that this works: ### >>> fromMeterToUnit(10, 'm') Decimal("10") >>> fromMeterToUnit(10, 'km') Decimal("0.010") >>> fromMeterToUnit(10, 'cm') Decimal("1.0E+3") >>> fromMeterToUnit(10, 'mm') Decimal("1.0E+4") ### Ok, looks good so far. And a similar definition for a 'fromUnitToMeter' isn't too much more work, and can reuse the same numbers in the table. (By the way, several other posters have mentioned that "unit tests" would be a really good idea to have. Do you know about them already? I'm sure many of us on the list can show examples and help you learn them if you'd like.) The big win here is that we don't have to repeat the same numbers: we want to avoid the chance of accidently mistyping a ratio --- we want to reduce redundancy in data if we can. And if we have to correct some numbers later on, it's nice if we can correct it just once, and not in several places. I think that Javier Ruere found the bug in one of the ratios, but I wanted to comment on the code's style, so that the main ideas of the converter stand out clearly. Best of wishes to you! _______________________________________________ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor