def float_to_decimal(f):
"""
Convert a floating point number to a Decimal with
no loss of information. Intended for Python 2.6 where
casting float to Decimal does not work.
"""
n, d = f.as_integer_ratio()
numerator, denominator = Decimal(n), Decimal(d)
ctx = Context(prec=60)
result = ctx.divide(numerator, denominator)
while ctx.flags[Inexact]:
ctx.flags[Inexact] = False
ctx.prec *= 2
result = ctx.divide(numerator, denominator)
return result
python类Context()的实例源码
_compat.py 文件源码
项目:Infrax-as-Code-1000-webservers-in-40-minutes
作者: ezeeetm
项目源码
文件源码
阅读 27
收藏 0
点赞 0
评论 0
def round_py2_compat(what):
"""
Python 2 and Python 3 use different rounding strategies in round(). This
function ensures that results are python2/3 compatible and backward
compatible with previous py2 releases
:param what: float
:return: rounded long
"""
d = Context(
prec=len(str(long(what))), # round to integer with max precision
rounding=decimal.ROUND_HALF_UP
).create_decimal(str(what)) # str(): python 2.6 compat
return long(d)
def float_to_decimal(f):
"""Convert a floating point number to a Decimal with no loss of information.
See: http://docs.python.org/release/2.6.7/library/decimal.html#decimal-faq
"""
n, d = f.as_integer_ratio()
numerator, denominator = Decimal(n), Decimal(d)
ctx = Context(prec=60)
result = ctx.divide(numerator, denominator)
while ctx.flags[Inexact]:
ctx.flags[Inexact] = False
ctx.prec *= 2
result = ctx.divide(numerator, denominator)
return result
def create_decimal128_context():
"""Returns an instance of :class:`decimal.Context` appropriate
for working with IEEE-754 128-bit decimal floating point values.
"""
opts = _CTX_OPTIONS.copy()
opts['traps'] = []
return decimal.Context(**opts)
def round_py2_compat(what):
"""
Python 2 and Python 3 use different rounding strategies in round(). This
function ensures that results are python2/3 compatible and backward
compatible with previous py2 releases
:param what: float
:return: rounded long
"""
d = Context(
prec=len(str(long(what))), # round to integer with max precision
rounding=decimal.ROUND_HALF_UP
).create_decimal(str(what)) # str(): python 2.6 compat
return long(d)
def _context_equal(x, y, ctx):
"""Return True if both objects are equal based on the provided context.
Args:
x (numeric): A numeric value.
y (numeric): A numeric value.
ctx (:class:`decimal.Context`): A decimal Context object.
Returns:
:obj:`bool`: True if the values are equal based on the provided
context, False otherwise.
"""
if x is not None:
if y is None:
return False
# Note: The float conversion is because these may come in as
# numpy.float32 or numpy.float64, which Decimal does not know
# how to handle.
if (Decimal(float(x)).normalize(ctx) !=
Decimal(float(y)).normalize(ctx)):
return False
else:
if y is not None:
return False
return True
def __eq__(self, other):
"""Return True if this projection object is the same as *other*.
Note: WRF can use either floats or doubles, so only going to
guarantee floating point precision equivalence, in case the different
types are ever compared (or a projection is hand constructed). For WRF
domains, 7-digit equivalence should be good enough.
"""
if self.map_proj is not None:
if self.map_proj != other.map_proj:
return False
else:
if other.map_proj is not None:
return False
# Only checking for floating point equal.
ctx = Context(prec=7, rounding=ROUND_HALF_UP)
return (WrfProj._context_equal(self.truelat1, other.truelat1, ctx) and
WrfProj._context_equal(self.truelat2, other.truelat2, ctx) and
WrfProj._context_equal(self.moad_cen_lat, other.moad_cen_lat,
ctx) and
WrfProj._context_equal(self.stand_lon, other.stand_lon,
ctx) and
WrfProj._context_equal(self.pole_lat, other.pole_lat, ctx) and
WrfProj._context_equal(self.pole_lon, other.pole_lon, ctx) and
WrfProj._context_equal(self.dx, other.dx, ctx) and
WrfProj._context_equal(self.dy, other.dy, ctx))
def round_py2_compat(what):
"""
Python 2 and Python 3 use different rounding strategies in round(). This
function ensures that results are python2/3 compatible and backward
compatible with previous py2 releases
:param what: float
:return: rounded long
"""
d = Context(
prec=len(str(long(what))), # round to integer with max precision
rounding=decimal.ROUND_HALF_UP
).create_decimal(str(what)) # str(): python 2.6 compat
return long(d)
def round_py2_compat(what):
"""
Python 2 and Python 3 use different rounding strategies in round(). This
function ensures that results are python2/3 compatible and backward
compatible with previous py2 releases
:param what: float
:return: rounded long
"""
d = Context(
prec=len(str(long(what))), # round to integer with max precision
rounding=decimal.ROUND_HALF_UP
).create_decimal(str(what)) # str(): python 2.6 compat
return long(d)
def bench_telco(loops, filename):
getcontext().rounding = ROUND_DOWN
rates = list(map(Decimal, ('0.0013', '0.00894')))
twodig = Decimal('0.01')
Banker = Context(rounding=ROUND_HALF_EVEN)
basictax = Decimal("0.0675")
disttax = Decimal("0.0341")
with open(filename, "rb") as infil:
data = infil.read()
infil = io.BytesIO(data)
outfil = six.StringIO()
start = perf.perf_counter()
for _ in range(loops):
infil.seek(0)
sumT = Decimal("0") # sum of total prices
sumB = Decimal("0") # sum of basic tax
sumD = Decimal("0") # sum of 'distance' tax
for i in xrange(5000):
datum = infil.read(8)
if datum == '':
break
n, = unpack('>Q', datum)
calltype = n & 1
r = rates[calltype]
p = Banker.quantize(r * n, twodig)
b = p * basictax
b = b.quantize(twodig)
sumB += b
t = p + b
if calltype:
d = p * disttax
d = d.quantize(twodig)
sumD += d
t += d
sumT += t
print(t, file=outfil)
outfil.seek(0)
outfil.truncate()
return perf.perf_counter() - start
def pretty_description(self, show_positions=True, filename=None):
if filename:
pfx = filename.rstrip().rstrip(':') + ':'
else:
pfx = ''
# Print file position as numeric abbreviation
err = pfx
if self.position == 0:
err += '0:0:'
elif self.position:
err += '%d:%d:' % (self.position.line, self.position.column)
else:
err += ' '
# Print severity and main error message
err += " %s: %s" % (self.severity.capitalize(), self.message)
if len(self.args) > 1:
err += ': '
for anum, a in enumerate(self.args[1:]):
if anum > 1:
err += ', '
astr = repr(a)
if len(astr) > 30:
astr = astr[:30] + '...'
err += astr
# Print out exception chain
e2 = self
while e2:
if hasattr(e2,'__cause__') and isinstance(e2.__cause__,Exception):
e2 = e2.__cause__
e2desc = str(e2).strip()
if not e2desc:
e2desc = repr(e2).strip()
err += "\n | Cause: %s" % e2desc.strip().replace('\n','\n | ')
else:
e2 = None
# Show file position
if show_positions and self.position is not None:
if self.position == 0:
err += "\n | At start of input"
else:
err += "\n | At %s" % (self.position.describe(show_text=False),)
if self.position.text_after:
err += "\n | near text: %r" % (self.position.text_after,)
# Show context
if show_positions and self.outer_position:
if self.context_description:
cdesc = self.context_description.capitalize()
else:
cdesc = "Context"
err += "\n | %s started at %s" % (cdesc, self.outer_position.describe(show_text=False),)
if self.outer_position.text_after:
err += "\n | with text: %r" % (self.outer_position.text_after,)
return err