A
ajaksu
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:
10 loops, best of 3: 283 ms per loop
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
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:
10 loops, best of 3: 12 ms per loopDecimal("7.252714899122810148399426210E+12378")
10 loops, best of 3: 283 ms per loop
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