Какой самый простой способ округлить десятичные числа в Python в контексте пользовательской функции? - PullRequest
0 голосов
/ 06 января 2019

Мне трудно работать с числами с плавающей запятой, и я считаю, что даже встроенный десятичный класс в 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'. С таким огромным методом, я чувствую, что нет простого способа исправить это? Должен ли я попытаться переписать новый метод с другим углом решения с округлением или он может быть включен в этот существующий метод? Спасибо.

Ответы [ 2 ]

0 голосов
/ 06 января 2019

Если вы хотите использовать десятичный модуль для этого, вы можете сделать:

decimal.Decimal(19.2189).quantize(decimal.Decimal(10) ** -3)

Метод quantize округляет десятичные дроби до количества десятичных знаков в своем аргументе (так что вы можете передать .001 вместо повышения десятичного знака до -3).

0 голосов
/ 06 января 2019

Использование round()

Вы можете использовать round() для этого.

>>> round(19.2189, 3)
19.219

Если вы хотите преобразовать это число в строку:

>>> str(round(19.2189, 3))
'19.219'

Использование format()

Вы также можете использовать format() для этого:

>>> format(19.2189, '.3f')
'19.219'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...