Вывод числа с плавающей точкой до определённого знака после запятой без округления

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 шт):

Автор решения: CrazyElf

У вас с обеими переменными происходит округление, просто во втором случае это совпадает с тем результатом, который вы хотите. Округление для чисел меньше 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
→ Ссылка
Автор решения: Fox Fox

В качестве идеи:

s = str(340.0098765678)
print(s[:s.find(".") + 6])

Выводит на экран: 340.00987

→ Ссылка
Автор решения: Stanislav Volodarskiy

Давайте попробуем формулу 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
→ Ссылка
Автор решения: Serge3leo

К сожалению, все ответы на 20.02.2025, имели те или иные неточности: некорректная обработка отрицательных чисел, игнорирование ошибки представления результата операции с плавающей точкой, некорректная обработка больших или маленьких чисел. Т.е. требовали обработки напильником.

Однако, есть вариант использования стандартной библиотеки Python:

import decimal
str(decimal.Decimal(j).quantize(decimal.Decimal("0.00001"),
                                rounding=decimal.ROUND_DOWN))

Есть неплохой шанс, что для этого варианта напильник не потребуется.

→ Ссылка