![]() |
|
|
|
#1 |
|
Posts: n/a
|
Hello c.l.p.ers
Running long(Decimal) is pretty slow, and the conversion is based on strings. I'm trying to figure out whether there is a good reason for using strings like in decimal.py (that reason would be bound to bite me down the road). This converts Decimal to long and is much faster in my test system (PIII 650MHz, but was written on a P133 a year ago def dec2long(number): """ Convert decimal.Decimal to long. Hopefully faster than C{int(Decimal())}. @param number: A C{decimal.Decimal} value @return: Long from input """ if not isinstance(number, Decimal): raise TypeError, "dec2long requires an instance of Decimal" elif number._is_special: if number._isnan(): raise TypeError, "This Decimal is NaN, an ex-Number" elif number._isinfinity(): raise OverflowError, "Cannot convert infinity to long" else: longstring = str(number) if "e" in longstring: longsplit = longstring.split("e") elif "E" in longstring: longsplit = longstring.split("E") else: longsplit = [longstring, "0"] floatexp = long(len(longsplit[0].split(".")[1])) ftol = long(Decimal(longsplit[0]) * 10L**floatexp) longexp = long(int(longsplit[1]) - floatexp) result = ftol * 10L**longexp return result For the sake of camparison, here's decimal.py __int__: def __int__(self): """Converts self to an int, truncating if necessary.""" [snip: error checking] if self._exp >= 0: s = ''.join(map(str, self._int)) + '0'*self._exp else: s = ''.join(map(str, self._int))[:self._exp] if s == '': s = '0' sign = '-'*self._sign return int(sign + s) Then, some timings: >> example Decimal("7.252714899122810148399426210E+12378") >> %timeit v = dec2long(example) 10 loops, best of 3: 12 ms per loop >> %timeit v = long(example) 10 loops, best of 3: 283 ms per loop >> dec2long(example) == long(example) True Some anachronisms (like 10L) and very probably mistakes are present in that old hack, but it makes decimal somewhat more interesting for me. The answer to this message might be "decimal will be written in C very soon, so nevermind", but I'd love to hear that in fact the following function is wrong and there is a good reason long(Decimal) works based on strings... or that my function is silly but could be corrected. Thanks in advance and best regards, Daniel 'ajaksu' Diniz PS: my use case is Stirling's approximation of the factorial for large numbers, feel free to criticize that, too |
|
|
|
#2 |
|
Posts: n/a
|
Sorry... I'm ashamed to submit such awful code in my first post. Let me
try again... from decimal import Decimal def dec2long(number): """ Convert decimal.Decimal to long """ longstring = str(number) if "e" in longstring: radix, exponent = longstring.split("e") elif "E" in longstring: radix, exponent = longstring.split("E") else: radix, exponent = [longstring, "0"] floatexp = long(len(radix.split(".")[1])) floatish = Decimal(radix) * 10L**floatexp ftol = long(floatish) longexp = long(int(exponent) - floatexp) return ftol * 10L**longexp This one should run by itself, is more readable and... still smells bad Sorry again. |
|
|
|
#3 |
|
Posts: n/a
|
In article < .com>,
ajaksu <> wrote: > >Running long(Decimal) is pretty slow, and the conversion is based on >strings. I'm trying to figure out whether there is a good reason for >using strings like in decimal.py (that reason would be bound to bite me >down the road). I'm not sure why it's coded that, but it's somewhat irrelevant: right now, work is being done to convert decimal.py to C code, which will almost certainly be much faster than your code. Generally speaking, you should not be using Decimal now with any expectation of speed. -- Aahz () <*> http://www.pythoncraft.com/ "Debugging is twice as hard as writing the code in the first place. Therefore, if you write the code as cleverly as possible, you are, by definition, not smart enough to debug it." --Brian W. Kernighan |
|
|
|
#4 |
|
Posts: n/a
|
Hi Aahz, thanks for the feedback!
Aahz wrote: > I'm not sure why it's coded that, but it's somewhat irrelevant: right > now, work is being done to convert decimal.py to C code, which will > almost certainly be much faster than your code. Generally speaking, you > should not be using Decimal now with any expectation of speed. Agreed and agreed. Just to avoid that the buggy (and unreadable) versions above harm anyone, here's a better attempt: def dec2long(number): """ Convert C{decimal.Decimal} to long """ decimal_string = str(number) ## Split 123.45E10 -> radix = 123.45, exponent = 10 if "e" in decimal_string: radix, exponent = decimal_string.split("e") elif "E" in decimal_string: radix, exponent = decimal_string.split("E") else: radix, exponent = (decimal_string, 0) if exponent: exponent = int(exponent) if "." in radix: ## radix = 123.45, radix_decimal_part_len = 2 radix_decimal_part_len = long(len(radix.split(".")[1])) ## radix = 123.45, radix_as_long = 123.45 * 10**2 = 12345 radix_as_long = long(Decimal(radix) * (10L**radix_decimal_part_len)) ##corrected_exponent = 10 - 2 = 8 corrected_exponent = exponent - radix_decimal_part_len ## return 12345 * 10**8 result = radix_as_long * 10L** corrected_exponent else: radix_as_long = long(radix) result = radix_as_long * 10L**exponent else: if "." in radix: radix_integer_part = long(radix.split(".")[0]) else: radix_integer_part = long(radix) result = radix_integer_part return result Working from inside decimal.py allows things to work faster, but anyone wanting speed REALLY shouldn't use Decimal ("Rational and arbitrary precision floating point numbers"): http://cheeseshop.python.org/pypi/clnum/1.2 Cheers, Daniel |
|
![]() |
| Thread Tools | Search this Thread |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Best CPU Cooler Performance LGA1366 Q2-2009 | Ian | Front Page News | 0 | 08-05-2009 03:56 PM |
| Windows 7 Beta Performance | Ian | Front Page News | 0 | 01-16-2009 01:53 PM |
| Does RAID0 Really Increase Disk Performance? | Silverstrand | Front Page News | 0 | 11-02-2006 01:09 AM |
| Re: Hard drive performance question | MF | A+ Certification | 0 | 12-10-2005 12:55 AM |
| Re: Hard drive performance question | John O | A+ Certification | 0 | 12-09-2005 08:31 PM |