Commit f4d8597a authored by Raymond Hettinger's avatar Raymond Hettinger

Issue 4796: Add from_float methods to the decimal module.

parent 0fa10b3c
......@@ -484,6 +484,29 @@ Decimal objects
.. versionadded:: 2.6
.. method:: from_float(f)
Classmethod that converts a float to a decimal number, exactly.
Note `Decimal.from_float(0.1)` is not the same as `Decimal('0.1')`.
Since 0.1 is not exactly representable in binary floating point, the
value is stored as the nearest representable value which is
`0x1.999999999999ap-4`. That equivalent value in decimal is
`0.1000000000000000055511151231257827021181583404541015625`.
.. doctest::
>>> Decimal.from_float(0.1)
Decimal('0.1000000000000000055511151231257827021181583404541015625')
>>> Decimal.from_float(float('nan'))
Decimal('NaN')
>>> Decimal.from_float(float('inf'))
Decimal('Infinity')
>>> Decimal.from_float(float('-inf'))
Decimal('-Infinity')
.. versionadded:: 2.7
.. method:: fma(other, third[, context])
Fused multiply-add. Return self*other+third with no rounding of the
......@@ -1007,6 +1030,26 @@ In addition to the three supplied contexts, new contexts can be created with the
If the argument is a string, no leading or trailing whitespace is
permitted.
.. method:: create_decimal_from_float(f)
Creates a new Decimal instance from a float *f* but rounding using *self*
as the context. Unlike the :method:`Decimal.from_float` class method,
the context precision, rounding method, flags, and traps are applied to
the conversion.
.. doctest::
>>> context = Context(prec=5, rounding=ROUND_DOWN)
>>> context.create_decimal_from_float(math.pi)
Decimal('3.1415')
>>> context = Context(prec=5, traps=[Inexact])
>>> context.create_decimal_from_float(math.pi)
Traceback (most recent call last):
...
Inexact: None
.. versionadded:: 2.7
.. method:: Etiny()
Returns a value equal to ``Emin - prec + 1`` which is the minimum exponent
......
This diff is collapsed.
......@@ -1361,6 +1361,55 @@ class DecimalPythonAPItests(unittest.TestCase):
r = d.to_integral(ROUND_DOWN)
self.assertEqual(Decimal(math.trunc(d)), r)
def test_from_float(self):
class MyDecimal(Decimal):
pass
r = MyDecimal.from_float(0.1)
self.assertEqual(type(r), MyDecimal)
self.assertEqual(str(r),
'0.1000000000000000055511151231257827021181583404541015625')
bigint = 12345678901234567890123456789
self.assertEqual(MyDecimal.from_float(bigint), MyDecimal(bigint))
self.assert_(MyDecimal.from_float(float('nan')).is_qnan())
self.assert_(MyDecimal.from_float(float('inf')).is_infinite())
self.assert_(MyDecimal.from_float(float('-inf')).is_infinite())
self.assertEqual(str(MyDecimal.from_float(float('nan'))),
str(Decimal('NaN')))
self.assertEqual(str(MyDecimal.from_float(float('inf'))),
str(Decimal('Infinity')))
self.assertEqual(str(MyDecimal.from_float(float('-inf'))),
str(Decimal('-Infinity')))
self.assertRaises(TypeError, MyDecimal.from_float, 'abc')
for i in range(200):
x = random.expovariate(0.01) * (random.random() * 2.0 - 1.0)
self.assertEqual(x, float(MyDecimal.from_float(x))) # roundtrip
def test_create_decimal_from_float(self):
context = Context(prec=5, rounding=ROUND_DOWN)
self.assertEqual(
context.create_decimal_from_float(math.pi),
Decimal('3.1415')
)
context = Context(prec=5, rounding=ROUND_UP)
self.assertEqual(
context.create_decimal_from_float(math.pi),
Decimal('3.1416')
)
context = Context(prec=5, traps=[Inexact])
self.assertRaises(
Inexact,
context.create_decimal_from_float,
math.pi
)
self.assertEqual(repr(context.create_decimal_from_float(-0.0)),
"Decimal('-0')")
self.assertEqual(repr(context.create_decimal_from_float(1.0)),
"Decimal('1')")
self.assertEqual(repr(context.create_decimal_from_float(10)),
"Decimal('10')")
class ContextAPItests(unittest.TestCase):
def test_pickle(self):
......
......@@ -12,8 +12,6 @@ What's New in Python 2.7 alpha 1
Core and Builtins
-----------------
- Issue #4817: Remove unused function PyOS_GetLastModificationTime.
- Issue #4075: Use OutputDebugStringW in Py_FatalError.
- Issue #4797: IOError.filename was not set when _fileio.FileIO failed to open
......@@ -110,6 +108,9 @@ Core and Builtins
Library
-------
- Issue #4796: Added Decimal.from_float() and Context.create_decimal_from_float()
to the decimal module.
- Issue #4812: add missing underscore prefix to some internal-use-only
constants in the decimal module. (Dec_0 becomes _Dec_0, etc.)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment