Мне трудно работать с числами с плавающей запятой, и я считаю, что даже встроенный десятичный класс в Python порой довольно запутан. В качестве решения я сам написал метод, который просто принимает значение и количество цифр, которые должны быть показаны после плавающей запятой, и возвращает строку в хорошем формате. Это выглядит так:
def format_to_decimal_string(value, decimal_places):
"""
# Given the `value` and `decimal_places`, this method returns a string
in the format of a decimal number. Eg: `format_to_decimal_string('99.99', 1)`
returns '99.9', while `format_to_decimal_string('99.99', 0)` return '99'.
# The arguments are validated, to make sure `value` can be turned into
a decimal number, and `decimal_places` is an integer greater than 0.
The `value` is first turned into a string to accomodate for edge-cases,
such as `format_to_decimal_string(99.99, 2)`.
# If `decimal_number` is zero, we return a formatted zero string.
# The start index is calculated, and using that, we append numbers
to the string. Once again, we make sure to add zeroes to the start
and/or the end if needed.
# Finally, we append the minus sign if needed, and return the result.
"""
# Validating arguments
try:
decimal_number = decimal.Decimal(str(value)).as_tuple()
except:
raise ValueError('The value is not a valid decimal number.')
if not isinstance(decimal_places, int):
raise ValueError('The given decimal places is not an integer.')
if not decimal_places >= 0:
raise ValueError('The given decimal places must be greater than or equal to zero.')
# Check if `decimal_number` is zero
if decimal_number == 0:
result = '0'
if not decimal_places == 0:
result += '.'
for i in range(decimal_places):
result += '0'
return result
# Finding the start index
exponent_start_index = len(decimal_number.digits) + decimal_number.exponent
# Appending the first digit
if exponent_start_index == 0:
result = '0'
else:
result = ''
for digit in decimal_number.digits[0:exponent_start_index]:
result += str(digit)
# Appending the exponents
exponent = ''
if not decimal_places == 0:
result += '.'
for digit in decimal_number.digits[exponent_start_index:(decimal_places + exponent_start_index)]:
exponent += str(digit)
# Adding extra zeroes to make the number have a valid precision
if decimal_places > len(exponent):
for i in range(decimal_places - len(exponent)):
exponent += '0'
# Combining the first digit and the exponents
result = result + exponent
# Appending the minus sign if needed
if decimal_number.sign == 1:
if not decimal.Decimal(result) == 0:
result = '-' + result
return result
Довольно понятно. Он также учитывает нули, просто чтобы вывод выглядел хорошо. Однако, одна вещь, о которой я полностью забыл, это округление чисел. Например, format_to_decimal_string(19.2189, 3)
возвращает '19.218'
, когда я хотел бы, чтобы он возвратил '19.219'
. С таким огромным методом, я чувствую, что нет простого способа исправить это? Должен ли я попытаться переписать новый метод с другим углом решения с округлением или он может быть включен в этот существующий метод? Спасибо.