python Decimal - checking if integer
I am using the Decimal library in Python, and printing out the values using
format(value, 'f')
, where value is a Decimal
. I get numbers in the form 10.00000
, which reflects the precision on the decimal. I know that float
supports is_integer
, but there seems to be a lack of a similar API for decimals. I was wondering if there was a way around this.
Solution 1:
You could use the modulo operation to check if there is a non-integer remainder:
>>> from decimal import Decimal
>>> Decimal('3.14') % 1 == 0
False
>>> Decimal('3') % 1 == 0
True
>>> Decimal('3.0') % 1 == 0
True
Solution 2:
Try math.floor(val) == val
or val == int(val)
.
Solution 3:
The mathematical solution is to convert your decimal number to integer and then test its equality with your number.
Since Decimal
can have an arbitrary precision, you should not convert it to int
or float
.
Fortunately, the Decimal
class has a to_integral_value
which make the conversion for you. You can adopt a solution like this:
def is_integer(d):
return d == d.to_integral_value()
Example:
from decimal import Decimal
d_int = Decimal(3)
assert is_integer(d_int)
d_float = Decimal(3.1415)
assert not is_integer(d_float)
See: http://docs.python.org/2/library/decimal.html#decimal.Decimal.to_integral_value
Solution 4:
Decimal does have a "hidden" method called _isinteger() that works kind of the like the float's is_integer() method:
>>> Decimal(1)._isinteger()
True
>>> Decimal(1.1)._isinteger()
Traceback (most recent call last):
File "C:\Program Files (x86)\Wing IDE 4.1\src\debug\tserver\_sandbox.py", line 1, in <module>
# Used internally for debug sandbox under external interpreter
File "C:\Python26\Lib\decimal.py", line 649, in __new__
"First convert the float to a string")
TypeError: Cannot convert float to Decimal. First convert the float to a string
As you can see, you would have to catch an exception though. Alternatively, you could do the test on the value BEFORE you pass it to Decimal using the float's method as you mentioned or by using isinstance.
Solution 5:
As of python 3.6, Decimal
has a method as_integer_ratio()
.
https://docs.python.org/3/library/decimal.html#decimal.Decimal.as_integer_ratio
as_integer_ratio()
returns a (numerator, denominator) tuple. If the denominator is 1, then the value is an integer.
>>> from decimal import Decimal
>>> Decimal("123.456").as_integer_ratio()[1] == 1
False
>>> Decimal("123.000").as_integer_ratio()[1] == 1
True