#python #python-3.x #floating-point #decimal #number-formatting
#python #python-3.x #с плавающей запятой #десятичный #форматирование чисел
Вопрос:
Я новичок в Python, и у меня возникли проблемы с десятичной функцией в модуле decimal в Python. Я понимаю, что из-за того, что Python хранит значения с плавающей запятой в памяти, чтобы выполнять вычисления над ними для получения удобочитаемого результата, мы можем либо использовать функцию round для нашего результата, либо использовать decimal .Функция Decimal() .
В приведенном ниже коде я создал класс calc1, который просто возвращает сложение и разность двух чисел. Тем не менее, всякий раз, когда я ее запускаю, даже если я включил decimal .Decimal() в моем коде результат продолжает быть неокругленным.
Код:
import decimal as dec
class calc1:
'calc1 class is used for addition, subtraction only'
obj_count = 0
def __init__(self, value1, value2):
self.value1 = value1
self.value2 = value2
calc1.obj_count = calc1.obj_count 1
def add(self):
return dec.Decimal(self.value1 self.value2)
def sub(self):
return dec.Decimal(self.value1 - self.value2)
def __str__(self):
return str(self.add()) " " str(self.sub())
obj_list = []
for i in range(5):
obj_list.append(calc1(3 * i, 5.6 * i))
print(obj_list[i])
Вывод:
0.0 0
8.6 -2.5999999999999996447286321199499070644378662109375
17.2 -5.199999999999999289457264239899814128875732421875
25.799999999999997 -7.7999999999999971578290569595992565155029296875
34.4 -10.39999999999999857891452847979962825775146484375
Комментарии:
1.
5.6
является собственным значением с плавающей запятой до того, как оно достигнетdecimal
модуля, и5.6 * i
выполняет собственную операцию с плавающей запятой без использованияdecimal
модуля. Я не часто использую Python и не используюdecimal
модуль, но я ожидаю, что вы захотите начать со"5.6"
строки, преобразовать ее вdecimal
значение, а затем продолжить арифметику оттуда, полностью избегая родной Python с плавающей запятой.
Ответ №1:
Ваша проблема в том, что вы передаете значение, которое уже имеет точность с плавающей запятой, вашему классу и, в свою очередь Decimal
, классу.
Вы можете избежать этого, просто передав Decimal
строковое представление числа, которое вы хотите присвоить ему.
from decimal import Decimal
class Calc1:
def __init__(self, val_1, val_2):
# these are now Decimal objects
self.val_1 = val_1
self.val_2 = val_2
def add(self):
# the Decimal conversion can be removed here
# since both numbers are already Decimals
return self.val_1 self.val_2
def sub(self):
return self.val_1 - self.val_2
def __str__(self):
return str(self.add()) " " str(self.sub())
lst = []
for i in range(5):
i_as_dec = Decimal(i)
# Here we multiply a decimal representation of each of our numbers
# this will hand a Decimal object to the Calc1 class
lst.append(Calc1(Decimal('3') * i_as_dec, Decimal('5.6') * i_as_dec))
print(lst[i])
Вывод:
0.0 0.0
8.6 -2.6
17.2 -5.2
25.8 -7.8
34.4 -10.4
Комментарии:
1. Есть ли какой-нибудь способ преобразовать переменную с плавающей запятой в десятичную? Я попытался передать значение с плавающей запятой, преобразованное в строку, в Decimal(), и, похоже, оно все еще работает только половину времени. Я только что отредактировал 2 строки в своем исходном коде: self.value1 = dec.Decimal(str(value1)) self.value2 = dec.Decimal(str(value2)) и это не сработало
2. Как я уже упоминал в ответе, если вы передаете какое-либо значение в виде числа с плавающей запятой, оно уже имеет точность с плавающей запятой. Например,
5.6 * 3
в вашем интерпретаторе возвращает16.799999999999997
. Передача этого значения вstr()
не изменит его каким-либо значимым образом перед преобразованием в строку. Ваш выбор — либо применить некоторый тип округления, либо начать с использованияDecimal
s в источнике, что и делает мой ответ.
Ответ №2:
Тем не менее, всякий раз, когда я ее запускаю, даже если я включил decimal .Decimal() в моем коде результат продолжает быть неокругленным.
Это соответствует тому, что decimal.Decimal
должно выполняться в соответствии с его документами:
класс decimal .Decimal(value=»0″, context= None) Создает новый десятичный объект на основе value . (…) Если value является числом с плавающей запятой, двоичное значение с плавающей запятой преобразуется без потерь в его точный десятичный эквивалент. Для этого преобразования часто может потребоваться 53 или более цифр точности. Например, Decimal(float(‘1.1’)) преобразуется в Decimal(‘1.1000000000000088817841970012523233890533447265625’).
В качестве примечания decimal.Decimal
— это класс, а не функция.
чтобы сгенерировать удобочитаемый результат, мы можем либо использовать функцию round для нашего результата, либо использовать decimal .Функция Decimal() .
Помимо этого вы можете решить отформатировать свой вывод, например, используя так называемые f-строки, например, если я хочу иметь 4 цифры после десятичной запятой:
x = 0.1 0.1 0.1
print(x) # 0.30000000000000004
print(f'{x:.4f}') # 0.3000
Имейте в виду, что f-string доступны только в python3.6 и новее, и если вам нужно использовать более старую версию, рассмотрите возможность использования других методов форматирования.
Комментарии:
1. Есть ли какой-либо способ преобразовать значение с плавающей запятой в десятичное в терминах самой переменной, а не использовать f-строку или какой-либо другой инструмент форматирования для простого изменения печатного вывода?