Mercurial > repos > shellac > guppy_basecaller
comparison env/lib/python3.7/site-packages/future/builtins/newround.py @ 2:6af9afd405e9 draft
"planemo upload commit 0a63dd5f4d38a1f6944587f52a8cd79874177fc1"
author | shellac |
---|---|
date | Thu, 14 May 2020 14:56:58 -0400 |
parents | 26e78fe6e8c4 |
children |
comparison
equal
deleted
inserted
replaced
1:75ca89e9b81c | 2:6af9afd405e9 |
---|---|
1 """ | |
2 ``python-future``: pure Python implementation of Python 3 round(). | |
3 """ | |
4 | |
5 from future.utils import PYPY, PY26, bind_method | |
6 | |
7 # Use the decimal module for simplicity of implementation (and | |
8 # hopefully correctness). | |
9 from decimal import Decimal, ROUND_HALF_EVEN | |
10 | |
11 | |
12 def newround(number, ndigits=None): | |
13 """ | |
14 See Python 3 documentation: uses Banker's Rounding. | |
15 | |
16 Delegates to the __round__ method if for some reason this exists. | |
17 | |
18 If not, rounds a number to a given precision in decimal digits (default | |
19 0 digits). This returns an int when called with one argument, | |
20 otherwise the same type as the number. ndigits may be negative. | |
21 | |
22 See the test_round method in future/tests/test_builtins.py for | |
23 examples. | |
24 """ | |
25 return_int = False | |
26 if ndigits is None: | |
27 return_int = True | |
28 ndigits = 0 | |
29 if hasattr(number, '__round__'): | |
30 return number.__round__(ndigits) | |
31 | |
32 if ndigits < 0: | |
33 raise NotImplementedError('negative ndigits not supported yet') | |
34 exponent = Decimal('10') ** (-ndigits) | |
35 | |
36 if PYPY: | |
37 # Work around issue #24: round() breaks on PyPy with NumPy's types | |
38 if 'numpy' in repr(type(number)): | |
39 number = float(number) | |
40 | |
41 if isinstance(number, Decimal): | |
42 d = number | |
43 else: | |
44 if not PY26: | |
45 d = Decimal.from_float(number).quantize(exponent, | |
46 rounding=ROUND_HALF_EVEN) | |
47 else: | |
48 d = from_float_26(number).quantize(exponent, rounding=ROUND_HALF_EVEN) | |
49 | |
50 if return_int: | |
51 return int(d) | |
52 else: | |
53 return float(d) | |
54 | |
55 | |
56 ### From Python 2.7's decimal.py. Only needed to support Py2.6: | |
57 | |
58 def from_float_26(f): | |
59 """Converts a float to a decimal number, exactly. | |
60 | |
61 Note that Decimal.from_float(0.1) is not the same as Decimal('0.1'). | |
62 Since 0.1 is not exactly representable in binary floating point, the | |
63 value is stored as the nearest representable value which is | |
64 0x1.999999999999ap-4. The exact equivalent of the value in decimal | |
65 is 0.1000000000000000055511151231257827021181583404541015625. | |
66 | |
67 >>> Decimal.from_float(0.1) | |
68 Decimal('0.1000000000000000055511151231257827021181583404541015625') | |
69 >>> Decimal.from_float(float('nan')) | |
70 Decimal('NaN') | |
71 >>> Decimal.from_float(float('inf')) | |
72 Decimal('Infinity') | |
73 >>> Decimal.from_float(-float('inf')) | |
74 Decimal('-Infinity') | |
75 >>> Decimal.from_float(-0.0) | |
76 Decimal('-0') | |
77 | |
78 """ | |
79 import math as _math | |
80 from decimal import _dec_from_triple # only available on Py2.6 and Py2.7 (not 3.3) | |
81 | |
82 if isinstance(f, (int, long)): # handle integer inputs | |
83 return Decimal(f) | |
84 if _math.isinf(f) or _math.isnan(f): # raises TypeError if not a float | |
85 return Decimal(repr(f)) | |
86 if _math.copysign(1.0, f) == 1.0: | |
87 sign = 0 | |
88 else: | |
89 sign = 1 | |
90 n, d = abs(f).as_integer_ratio() | |
91 # int.bit_length() method doesn't exist on Py2.6: | |
92 def bit_length(d): | |
93 if d != 0: | |
94 return len(bin(abs(d))) - 2 | |
95 else: | |
96 return 0 | |
97 k = bit_length(d) - 1 | |
98 result = _dec_from_triple(sign, str(n*5**k), -k) | |
99 return result | |
100 | |
101 | |
102 __all__ = ['newround'] |