Вывод числа с плавающей точкой до определённого знака после запятой без округления
j=float(0.15+0.005*62)
print(j)#0.45999999999999996
number = 3.1415926535
formatted_number = f"{j:.5f}"
print(formatted_number) #выводит 46.00000
formatted_number = f"{number:.5f}"
print(formatted_number) #выводит 3.14159
Мне нужно оставить в переменной j=0.45999999999999996 5 знаков после запятой без округления, но все время округляется. Причем с одной переменной работает корректно, с другой нет. Как решить проблему? Мне обязательно нужно не просто вывести число, но и записать его значение.
Ответы (4 шт):
У вас с обеими переменными происходит округление, просто во втором случае это совпадает с тем результатом, который вы хотите. Округление для чисел меньше 5 происходит вниз, поэтому так.
Для вывода нужного числа знаков проще всего воспользоваться таким способом:
print(j - j % 1e-5)
# 0.45999
Просто отбрасываем из числа остаток от деления его на 0.00001
.
Если вдруг этот метод вам не подойдёт по каким-то причинам, то можно подсмотреть и другие методы на английском СО.
P.S. Насчёт взятия остатка от деления на 0.00001
смотрим Деление с остатком, формула для получения остатка:
q = [a/b]
r = a - b*q
Подставим наши значения:
q = [0.45999999999999996 / 0.00001] = [0.45999999999999996 * 100000] = [45999.999999999996] = 45999
r = 0.45999999999999996 - 0.00001 * 45999 = 0.45999999999999996 - 0.45999 = 0.00000999999999996
Легко видеть, что этот остаток от деления - это как-раз то, что нам нужно вычесть из исходного числа, чтобы получить 0.45999
:
0.45999999999999996 - 0.45999 = 0.00000999999999996
0.45999 = 0.45999999999999996 - 0.00000999999999996
В качестве идеи:
s = str(340.0098765678)
print(s[:s.find(".") + 6])
Выводит на экран: 340.00987
Давайте попробуем формулу x - x % 1e-5
:
$ python Python 3.11.2 (main, Nov 30 2024, 21:22:50) [GCC 12.2.0] on linux Type "help", "copyright", "credits" or "license" for more information. @>>> x = 0.15 + 0.005 * 62 @>>> print(x) 0.45999999999999996 @>>> print(x - x % 1e-5) 0.45999
Пока отлично работает. Но надо помнить, что 10-k не представляются вещественными числами точно. Иногда будет получаться немного больше:
@>>> print(x - x % 1e-4) 0.45990000000000003
Иногда немного меньше:
@>>> print(x - x % 1e-7) 0.45999989999999996
Чтобы стало лучше, нужно результат отформатировать перед печатью:
@>>> print(f'{x - x % 1e-4:.4}') 0.4599 @>>> print(f'{x - x % 1e-7:.7}') 0.4599999
Не проще ли тогда напечатать число x в строку и просто отрезать сколько нужно знаков после запятой?
Если нет желания работать со строками, есть точноe решение. Оно состоит в переводе вещественного числа в рациональную дробь n/d. Тогда выражение ⌊n·10i/d⌋ содержит все значащие цифры ответа. Переведите его в строку и вставьте точку в нужное место:
def to_str(x, i):
n, d = x.as_integer_ratio()
s = str(n * 10 ** i // d)
j = len(s) - i
if j > 0:
return f'{s[:j]}.{s[j:]}'
return f'0.{"0" * -j}{s}'
x = 0.15 + 0.005 * 62
for i in range(20):
print(f'{i:2}', to_str(x, i))
$ python to_str.py 0 0. 1 0.4 2 0.45 3 0.459 4 0.4599 5 0.45999 6 0.459999 7 0.4599999 8 0.45999999 9 0.459999999 10 0.4599999999 11 0.45999999999 12 0.459999999999 13 0.4599999999999 14 0.45999999999999 15 0.459999999999999 16 0.4599999999999999 17 0.45999999999999996 18 0.459999999999999964 19 0.4599999999999999644
К сожалению, все ответы на 20.02.2025, имели те или иные неточности: некорректная обработка отрицательных чисел, игнорирование ошибки представления результата операции с плавающей точкой, некорректная обработка больших или маленьких чисел. Т.е. требовали обработки напильником.
Однако, есть вариант использования стандартной библиотеки Python:
import decimal
str(decimal.Decimal(j).quantize(decimal.Decimal("0.00001"),
rounding=decimal.ROUND_DOWN))
Есть неплохой шанс, что для этого варианта напильник не потребуется.