Po przejrzeniu odpowiedzi na kilka podobnych pytań wydaje mi się to najlepszym rozwiązaniem:
def floatToString(inputValue):
return ('%.15f' % inputValue).rstrip('0').rstrip('.')
Moje rozumowanie:
%g
nie pozbywa się notacji naukowej.
>>> '%g' % 0.000035
'3.5e-05'
15 miejsc po przecinku wydaje się unikać dziwnego zachowania i ma dużą precyzję na moje potrzeby.
>>> ('%.15f' % 1.35).rstrip('0').rstrip('.')
'1.35'
>>> ('%.16f' % 1.35).rstrip('0').rstrip('.')
'1.3500000000000001'
Mógłbym użyć format(inputValue, '.15f').
zamiast '%.15f' % inputValue
, ale to trochę wolniej (~ 30%).
Mógłbym użyć Decimal(inputValue).normalize()
, ale ma to również kilka problemów. Po pierwsze, jest DUŻO wolniejszy (~ 11x). Odkryłem również, że chociaż ma dość dużą precyzję, nadal cierpi z powodu utraty precyzji podczas używania normalize()
.
>>> Decimal('0.21000000000000000000000000006').normalize()
Decimal('0.2100000000000000000000000001')
>>> Decimal('0.21000000000000000000000000006')
Decimal('0.21000000000000000000000000006')
Co najważniejsze, nadal będę się zmieniał Decimal
z tego, float
co może sprawić, że skończysz na czymś innym niż liczba, którą tam umieściłeś. Myślę, że Decimal
działa najlepiej, gdy arytmetyka pozostaje w środku Decimal
i Decimal
jest inicjalizowana ciągiem znaków.
>>> Decimal(1.35)
Decimal('1.350000000000000088817841970012523233890533447265625')
>>> Decimal('1.35')
Decimal('1.35')
Jestem pewien, że kwestię precyzji Decimal.normalize()
można dopasować do tego, co jest potrzebne przy użyciu ustawień kontekstowych, ale biorąc pod uwagę już małą prędkość i niepotrzebną niedorzeczną precyzję, a także fakt, że i tak będę konwertować z liczby zmiennoprzecinkowej i tracę precyzję, nie zrobiłem tego nie sądzę, że warto było to kontynuować.
Nie przejmuję się możliwym wynikiem „-0”, ponieważ -0.0 jest prawidłową liczbą zmiennoprzecinkową i prawdopodobnie byłoby to rzadkie zjawisko, ale ponieważ wspomniałeś, że chcesz, aby wynik łańcucha był jak najkrótszy, zawsze może zastosować dodatkowy warunek przy bardzo niewielkim koszcie dodatkowej prędkości.
def floatToString(inputValue):
result = ('%.15f' % inputValue).rstrip('0').rstrip('.')
return '0' if result == '-0' else result
3.14 == 3.140
- Są to te same liczby zmiennoprzecinkowe. W tym przypadku 3.140000 to ta sama liczba zmiennoprzecinkowa. Zero nie istnieje w ogóle.