Dopo aver esaminato le risposte a diverse domande simili, questa sembra essere la soluzione migliore per me:
def floatToString(inputValue):
return ('%.15f' % inputValue).rstrip('0').rstrip('.')
Il mio ragionamento:
%g
non si libera della notazione scientifica.
>>> '%g' % 0.000035
'3.5e-05'
15 decimali sembrano evitare comportamenti strani e hanno molta precisione per le mie esigenze.
>>> ('%.15f' % 1.35).rstrip('0').rstrip('.')
'1.35'
>>> ('%.16f' % 1.35).rstrip('0').rstrip('.')
'1.3500000000000001'
Avrei potuto usare format(inputValue, '.15f').
invece di '%.15f' % inputValue
, ma è un po 'più lento (~ 30%).
Avrei potuto usare Decimal(inputValue).normalize()
, ma questo ha anche alcuni problemi. Per uno, è MOLTO più lento (~ 11x). Ho anche scoperto che sebbene abbia una precisione abbastanza grande, soffre comunque di una perdita di precisione durante l'utilizzo normalize()
.
>>> Decimal('0.21000000000000000000000000006').normalize()
Decimal('0.2100000000000000000000000001')
>>> Decimal('0.21000000000000000000000000006')
Decimal('0.21000000000000000000000000006')
Ancora più importante, mi convertirei ancora Decimal
da un float
che può farti finire con qualcosa di diverso dal numero che hai inserito. Penso che Decimal
funzioni meglio quando l'aritmetica rimane Decimal
e Decimal
viene inizializzata con una stringa.
>>> Decimal(1.35)
Decimal('1.350000000000000088817841970012523233890533447265625')
>>> Decimal('1.35')
Decimal('1.35')
Sono sicuro che il problema della precisione di Decimal.normalize()
può essere adattato a ciò che è necessario utilizzando le impostazioni di contesto, ma considerando la già bassa velocità e non avendo bisogno di una precisione ridicola e il fatto che mi sarei comunque convertito da un galleggiante e perdere comunque la precisione, non l'ho fatto penso che valga la pena perseguire.
Non mi preoccupo del possibile risultato "-0" poiché -0,0 è un numero in virgola mobile valido e probabilmente sarebbe comunque un evento raro, ma poiché hai menzionato che vuoi mantenere il risultato della stringa il più breve possibile, tu potrebbe sempre utilizzare un ulteriore condizionale a costi di velocità extra molto ridotti.
def floatToString(inputValue):
result = ('%.15f' % inputValue).rstrip('0').rstrip('.')
return '0' if result == '-0' else result
3.14 == 3.140
- Sono lo stesso numero in virgola mobile. Del resto 3.140000 è lo stesso numero in virgola mobile. Lo zero non esiste in primo luogo.