Я хочу удалить цифры из числа с плавающей запятой, чтобы иметь фиксированное количество цифр после точки, например:
1.923328437452 -> 1.923
Мне нужно выводить строку в другую функцию, а не печатать.
Также я хочу игнорировать потерянные цифры, а не округлять их.
python
floating-point
Джоан Венге
источник
источник
Ответы:
Во-первых, функция для тех, кто просто хочет скопировать и вставить код:
Это действительно в Python 2.7 и 3.1+. Для более старых версий невозможно получить тот же эффект «интеллектуального округления» (по крайней мере, не без большого количества сложного кода), но округление до 12 десятичных знаков перед усечением будет работать большую часть времени:
объяснение
Суть базового метода состоит в том, чтобы преобразовать значение в строку с полной точностью, а затем просто отрубить все, что превышает желаемое количество символов. Последний шаг прост; это можно сделать либо с помощью строковых манипуляций
или
decimal
модульПервый шаг, преобразование в строку, довольно сложен, потому что есть несколько пар литералов с плавающей запятой (то есть то, что вы пишете в исходном коде), которые оба производят одно и то же двоичное представление, но должны быть по-разному усечены. Например, рассмотрим 0,3 и 0,29999999999999998. Если вы пишете
0.3
программу Python, компилятор кодирует ее, используя формат с плавающей запятой IEEE, в последовательность битов (при условии 64-битного числа с плавающей запятой)Это ближайшее значение к 0,3, которое может быть точно представлено как число с плавающей запятой IEEE. Но если вы пишете
0.29999999999999998
программу Python, компилятор переводит ее в точно такое же значение . В одном случае вы имели в виду его усечение (до одной цифры) как0.3
, тогда как в другом случае вы имели в виду его усечение как0.2
, но Python может дать только один ответ. Это фундаментальное ограничение Python или любого другого языка программирования без ленивых вычислений. Функция усечения имеет доступ только к двоичному значению, хранящемуся в памяти компьютера, а не к строке, которую вы фактически ввели в исходный код. 1Если вы декодируете последовательность битов обратно в десятичное число, снова используя 64-битный формат с плавающей запятой IEEE, вы получите
поэтому возникнет наивная реализация,
0.2
даже если это, вероятно, не то, что вы хотите. Подробнее об ошибке представления с плавающей запятой см. В учебнике Python .Очень редко приходится работать со значением с плавающей запятой, которое так близко к круглому числу, но намеренно не равно этому круглому числу. Таким образом, при усечении, вероятно, имеет смысл выбрать «самое красивое» десятичное представление из всего, что может соответствовать значению в памяти. Python 2.7 и выше (но не 3.0) включает в себя сложный алгоритм для этого , доступ к которому мы можем получить с помощью операции форматирования строк по умолчанию.
Единственное предостережение: это действует как
g
спецификация формата в том смысле, что в нем используется экспоненциальная запись (1.23e+4
), если число велико или достаточно мало. Таким образом, метод должен уловить этот случай и обработать его по-другому. Есть несколько случаев, когда использованиеf
спецификации формата вместо этого вызывает проблему, например, попытка усечения3e-10
до 28 цифр точности (это дает0.0000000002999999999999999980
), и я еще не уверен, как лучше всего с этим справиться.Если вы на самом деле являетесь работой с
float
S, которые очень близка к округлить , но намеренно не приравненную к ним (как 0.29999999999999998 или 99.959999999999994), это будет производить некоторые ложные срабатывания, то есть это будут круглые цифры , которые вы не хотите округленной. В этом случае решение состоит в том, чтобы указать фиксированную точность.Используемое здесь количество цифр точности не имеет значения, оно должно быть достаточно большим, чтобы гарантировать, что любое округление, выполняемое при преобразовании строки, не «увеличивает» значение до его красивого десятичного представления. Думаю,
sys.float_info.dig + n + 2
может быть достаточно во всех случаях, но если нет, то,2
возможно, придется увеличить, и это не повредит.В более ранних версиях Python (до 2.6 или 3.0) форматирование чисел с плавающей запятой было намного более грубым и регулярно приводило к таким вещам, как
Если это ваша ситуация, если вы действительно хотите использовать "хорошие" десятичные представления для усечения, все, что вы можете сделать (насколько мне известно), - это выбрать некоторое количество цифр, меньшее, чем полная точность, представленная a
float
, и округлить число до этого количества цифр перед его усечением. Типичный выбор - 12,но вы можете настроить это в соответствии с используемыми числами.
+1 Ну ... соврал. Технически вы можете указать Python повторно проанализировать собственный исходный код и извлечь часть, соответствующую первому аргументу, который вы передаете функции усечения. Если этот аргумент является литералом с плавающей запятой, вы можете просто отрезать его через определенное количество знаков после десятичной точки и вернуть его. Однако эта стратегия не работает, если аргумент является переменной, что делает ее бесполезной. Следующее представлено только для развлечения:
Обобщение этого для обработки случая, когда вы передаете переменную, кажется безнадежным делом, поскольку вам придется отслеживать выполнение программы в обратном направлении, пока вы не найдете литерал с плавающей запятой, который дал переменной ее значение. Если он вообще есть. Большинство переменных будут инициализированы из пользовательского ввода или математических выражений, и в этом случае двоичное представление - это все, что есть.
источник
applymap()
). Может быть, есть способ сделать всю операцию более эффективной, но это уже отдельный вопрос.См . Документацию Python по стандартным типам . Вам нужно будет немного прокрутить вниз, чтобы перейти к функции раунда. По сути, второе число говорит, до скольких знаков после запятой нужно округлить.
источник
Результатом
round
является число с плавающей запятой, поэтому будьте осторожны (пример взят из Python 2.6):Вам будет лучше при использовании форматированной строки:
источник
round(1.23456, 3)
есть1.235
и нет1.2350000000000001
источник
2
, у вас будет десятичная точка.
в конце строки - я думаю, не совсем хорошее решение.В моем приглашении Python 2.7:
>>> int(1.923328437452 * 1000)/1000.0 1.923
источник
Простой скрипт на Python -
источник
Это должно работать. Это должно дать вам усечение, которое вы ищете.
источник
Истинно питонический способ сделать это
или короче:
Обновить
Обычно проблема не в усечении самого числа с плавающей запятой, а в неправильном использовании чисел с плавающей запятой перед округлением.
Например:
int(0.7*3*100)/100 == 2.09
.Если вы вынуждены использовать числа с плавающей запятой (скажем, вы ускоряете свой код
numba
), лучше использовать центы как «внутреннее представление» price: (70*3 == 210
) и умножать / делить входы / выходы.источник
int(0.7*3*100)/100 == 2.09
. Куда ушел мой 1 цент?ImportError: cannot import name 'D'
я считаю , что вы хотели сделать с именем импорта нет?Многие ответы на этот вопрос совершенно неверны. Они либо округляют числа с плавающей запятой (а не усекают), либо работают не во всех случаях.
Это лучший результат Google, когда я ищу «Python truncate float», концепция, которая действительно проста и заслуживает лучших ответов. Я согласен с Хэтчкинсом в том, что использование
decimal
модуля - это питонический способ сделать это, поэтому я привожу здесь функцию, которая, как мне кажется, правильно отвечает на вопрос и которая работает должным образом во всех случаях.В качестве примечания, дробные значения, как правило, не могут быть точно представлены двоичными переменными с плавающей запятой (см. Здесь обсуждение этого), поэтому моя функция возвращает строку.
источник
Я сделал что-то вроде этого:
источник
Ты можешь сделать:
тестирование:
источник
Если вам нравится математика, это работает для положительных чисел:
источник
При использовании pandas df это сработало для меня
источник
Просто хотел упомянуть, что старый трюк "make round () with floor ()"
можно повернуть, чтобы сделать пол () из круглого ()
Хотя оба эти правила нарушают отрицательные числа, их использование далеко не идеально:
источник
int (16,5); это даст целочисленное значение 16, т.е. trunc, не сможет указывать десятичные дроби, но думаю, вы можете сделать это с помощью
источник
Вот простой способ:
для num = 1.923328437452 это выводит 1.923
источник
источник
Общая и простая функция:
источник
В python 3 есть простой обходной путь. Где вырезать, я определил с помощью переменной decPlace, чтобы облегчить адаптацию.
Вывод:
Надеюсь, поможет.
источник
источник
Краткий и легкий вариант
источник
На мой взгляд, большинство ответов слишком сложны, как насчет этого?
Просто ищите индекс '.' и обрезать по желанию (без округления). Конвертируйте строку в float в качестве последнего шага.
Или в вашем случае, если вы получаете число с плавающей запятой в качестве ввода и хотите получить строку в качестве вывода:
источник
# разделить и умножить на 10 ** количество желаемых цифр
источник
используйте numpy.round
источник
Что-то достаточно простое, чтобы поместиться в понимание списка, без библиотек или других внешних зависимостей. Для Python> = 3.6 очень просто писать f-строками.
Идея состоит в том, чтобы позволить строковому преобразованию выполнить округление на одно место больше, чем вам нужно, а затем отрубить последнюю цифру.
Конечно, здесь происходит округление (а именно для четвертой цифры), но округления в какой-то момент нельзя избежать. В случае, если важен переход между усечением и округлением, вот немного лучший пример:
Бонус: удаление нулей справа
источник
Идея ядра дается здесь , мне кажется , лучший подход к этой проблеме. К сожалению, он получил меньше голосов, в то время как более поздний ответ с большим количеством голосов не является полным (как отмечено в комментариях). Будем надеяться, что приведенная ниже реализация предоставляет краткое и полное решение для усечения .
который должен позаботиться обо всех угловых случаях, найденных здесь и здесь .
источник
Я также новичок в питоне, и после использования некоторых кусочков здесь я предлагаю свои два цента
str (int (time.time ())) возьмет временную эпоху как int и преобразует ее в строку и соединится с ... str (datetime.now (). microsecond) [: 3], который возвращает только микросекунды, преобразовать для строки и усечения до первых 3 символов
источник
источник
Если вы имеете в виду при печати, то должно работать следующее:
источник