После просмотра ответов на несколько похожих вопросов, мне кажется, это лучшее решение:
def floatToString(inputValue):
return ('%.15f' % inputValue).rstrip('0').rstrip('.')
Мои рассуждения:
%g
не избавляется от научной нотации.
>>> '%g' % 0.000035
'3.5e-05'
15 знаков после запятой, кажется, избегают странного поведения и обладают достаточной точностью для моих нужд.
>>> ('%.15f' % 1.35).rstrip('0').rstrip('.')
'1.35'
>>> ('%.16f' % 1.35).rstrip('0').rstrip('.')
'1.3500000000000001'
Я мог бы использовать format(inputValue, '.15f').
вместо '%.15f' % inputValue
, но это немного медленнее (~ 30%).
Я мог бы использовать Decimal(inputValue).normalize()
, но это также имеет несколько проблем. Во-первых, это НАМНОГО медленнее (~ 11x). Я также обнаружил, что, хотя он имеет довольно большую точность, он все еще страдает от потери точности при использовании normalize()
.
>>> Decimal('0.21000000000000000000000000006').normalize()
Decimal('0.2100000000000000000000000001')
>>> Decimal('0.21000000000000000000000000006')
Decimal('0.21000000000000000000000000006')
Самое главное, что я все равно буду переходить Decimal
с а, float
что может заставить вас получить что-то, кроме числа, которое вы там указали. Я думаю, что Decimal
лучше всего работает, когда арифметика остается Decimal
и Decimal
инициализируется строкой.
>>> Decimal(1.35)
Decimal('1.350000000000000088817841970012523233890533447265625')
>>> Decimal('1.35')
Decimal('1.35')
Я уверен, что проблема точности Decimal.normalize()
может быть приспособлена к тому, что необходимо, используя настройки контекста, но учитывая и без того медленную скорость и не требуя смешной точности и того факта, что я все равно буду конвертировать с плавающей запятой и теряя точность в любом случае, я не Не думаю, что это стоит того, чтобы преследовать.
Меня не интересует возможный результат "-0", так как -0.0 является допустимым числом с плавающей запятой, и, возможно, это будет редким случаем в любом случае, но так как вы упомянули, что хотите сохранить строковый результат как можно более коротким, вы всегда можно использовать дополнительные условия при очень небольших дополнительных затратах на скорость.
def floatToString(inputValue):
result = ('%.15f' % inputValue).rstrip('0').rstrip('.')
return '0' if result == '-0' else result
3.14 == 3.140
- Это одно и то же число с плавающей запятой. В этом отношении 3.140000 - это то же самое число с плавающей точкой. Ноль не существует в первую очередь.