Я использую стандартный модуль json в python 2.6 для сериализации списка чисел с плавающей запятой. Однако я получаю такие результаты:
>>> import json
>>> json.dumps([23.67, 23.97, 23.87])
'[23.670000000000002, 23.969999999999999, 23.870000000000001]'
Я хочу, чтобы числа с плавающей запятой состояли только из двух десятичных цифр. Результат должен выглядеть так:
>>> json.dumps([23.67, 23.97, 23.87])
'[23.67, 23.97, 23.87]'
Я попытался определить свой собственный класс JSON Encoder:
class MyEncoder(json.JSONEncoder):
def encode(self, obj):
if isinstance(obj, float):
return format(obj, '.2f')
return json.JSONEncoder.encode(self, obj)
Это работает для единственного плавающего объекта:
>>> json.dumps(23.67, cls=MyEncoder)
'23.67'
Но не работает для вложенных объектов:
>>> json.dumps([23.67, 23.97, 23.87])
'[23.670000000000002, 23.969999999999999, 23.870000000000001]'
Я не хочу иметь внешние зависимости, поэтому предпочитаю использовать стандартный модуль json.
Как я могу этого добиться?
источник
original_float_repr = encoder.FLOAT_REPR
encoder.FLOAT_REPR = lambda o: format(o, '.2f')
print json.dumps(1.0001)
encoder.FLOAT_REPR = original_float_repr
23.67
увидеть, как.2f
это не соблюдается.испускает
Никакой обезьяны не требуется.
источник
pretty_floats
функцию и просто интегрировал ее в свой другой код.list( map(pretty_floats, obj) )
map
возвращает итератор, а не alist
Если вы используете Python 2.7, простое решение - просто явно округлить ваши числа с плавающей запятой до желаемой точности.
Это работает, потому что Python 2.7 сделал округление с плавающей запятой более последовательным . К сожалению, это не работает в Python 2.6:
Упомянутые выше решения являются обходными путями для версии 2.6, но ни одно из них не является полностью адекватным. Исправление обезьяны json.encoder.FLOAT_REPR не работает, если ваша среда выполнения Python использует версию C модуля JSON. Класс PrettyFloat в ответе Тома Вутке работает, но только если кодировка% g работает глобально для вашего приложения. % .15g - это немного волшебство, оно работает, потому что точность с плавающей запятой составляет 17 значащих цифр, а% g не выводит конечные нули.
Я потратил некоторое время, пытаясь создать PrettyFloat, который позволял бы настраивать точность для каждого числа. Т.е. синтаксис вроде
Это непросто сделать правильно. Наследование от float неудобно. Наследование от Object и использование подкласса JSONEncoder с его собственным методом default () должно работать, за исключением того, что модуль json, похоже, предполагает, что все настраиваемые типы должны быть сериализованы как строки. То есть: вы получите строку Javascript «0,33» на выходе, а не число 0,33. Возможно, еще есть способ заставить эту работу работать, но это сложнее, чем кажется.
источник
Очень жаль, что
dumps
вы не можете ничего делать с плавающими. Однакоloads
делает. Так что, если вы не возражаете против дополнительной загрузки процессора, вы можете пропустить его через кодировщик / декодер / кодировщик и получить правильный результат:источник
parse_float
кварг!Вот решение, которое сработало для меня в Python 3 и не требует исправления обезьяны:
Выход:
Он копирует данные, но с округленными числами.
источник
Если вы застряли с Python 2.5 или более ранними версиями: трюк с обезьяньим патчем, похоже, не работает с исходным модулем simplejson, если установлены ускорения C:
источник
Вы можете делать то, что вам нужно, но это не задокументировано:
источник
FLOAT_REPR
вjson.encoder
модуле константу .Решение Alex Martelli будет работать для однопоточных приложений, но может не работать для многопоточных приложений, которым необходимо контролировать количество десятичных знаков в потоке. Вот решение, которое должно работать в многопоточных приложениях:
Вы можете просто установить encoder.thread_local.decimal_places на желаемое количество десятичных знаков, и следующий вызов json.dumps () в этом потоке будет использовать это количество десятичных знаков.
источник
Если вам нужно сделать это в python 2.7 без переопределения глобального json.encoder.FLOAT_REPR, вот один способ.
Затем в python 2.7:
В python 2.6 это не совсем работает, как указывает Мэтью Шинкель ниже:
источник
Плюсы:
Минусы:
Квадратичная сложность.
источник
При импорте стандартного модуля json достаточно изменить кодировщик по умолчанию FLOAT_REPR. На самом деле нет необходимости импортировать или создавать экземпляры Encoder.
Иногда также очень полезно выводить в формате json лучшее представление, которое Python может угадать с помощью str. Это гарантирует, что значащие цифры не будут проигнорированы.
источник
Я согласен с @Nelson в том, что наследование от float неудобно, но, возможно, решение, касающееся только
__repr__
функции, может быть простительным. В итоге я использовалdecimal
пакет для этого, чтобы при необходимости переформатировать поплавки. Положительным моментом является то, что это работает во всех контекстах, в которыхrepr()
вызывается, а также при простой печати списков, например, в стандартный вывод. Кроме того, точность настраивается во время выполнения после создания данных. Обратной стороной является, конечно, то, что ваши данные должны быть преобразованы в этот специальный класс с плавающей запятой (поскольку, к сожалению, вы не можете использовать патч обезьяныfloat.__repr__
). Для этого я предлагаю краткую функцию преобразования.Код:
Пример использования:
источник
Использование numpy
Если у вас действительно длинные числа с плавающей запятой, вы можете правильно округлить их вверх / вниз с помощью numpy:
'[23.67, 23.97, 23.87]'
источник
Я только что выпустил fjson , небольшую библиотеку Python для решения этой проблемы. Установить с помощью
и используйте так же
json
, с добавлениемfloat_format
параметра:источник