Muszę zaokrąglić liczbę zmiennoprzecinkową, aby była wyświetlana w interfejsie użytkownika. Np. Do jednej znaczącej liczby:
1234 -> 1000
0,12 -> 0,1
0,012 -> 0,01
0,062 -> 0,06
6253 -> 6000
1999 -> 2000
Czy istnieje dobry sposób na zrobienie tego za pomocą biblioteki Python, czy też muszę sam to napisać?
Odpowiedzi:
Możesz użyć liczb ujemnych do zaokrąglenia liczb całkowitych:
Zatem jeśli potrzebujesz tylko najbardziej znaczącej cyfry:
Prawdopodobnie będziesz musiał zadbać o zmianę liczby zmiennoprzecinkowej na liczbę całkowitą, jeśli jest większa niż 1.
źródło
log10
jest jedynym właściwym sposobem określenia sposobu zaokrąglenia.log10(abs(x))
, w przeciwnym razie liczby ujemne zawiodą (ix == 0
oczywiście traktuj osobno)round_to_n = lambda x, n: x if x == 0 else round(x, -int(math.floor(math.log10(abs(x)))) + (n - 1))
chroni przedx==0
ix<0
dziękuję @RoyHyunjinHan i @TobiasKienzler. Nie jest chroniony przed niezdefiniowanymi, takimi jak math.inf, ani śmieciami, takimi jak None itp.% g w formatowaniu łańcucha sformatuje liczbę zmiennoprzecinkową zaokrągloną do pewnej liczby cyfr znaczących. Czasami używa notacji naukowej 'e', więc przekonwertuj zaokrąglony ciąg z powrotem na zmiennoprzecinkowy, a następnie przez formatowanie ciągu% s.
źródło
0.075
do0.08
.0.07
Zamiast tego wraca .round_sig = lambda f,p: float(('%.' + str(p) + 'e') % f)
pozwala dostosować liczbę cyfr znaczących!Jeśli chcesz mieć inne niż 1 znaczące miejsce po przecinku (w przeciwnym razie to samo co Evgeny):
źródło
0.075
do0.08
.0.07
Zamiast tego wraca .round
. docs.python.org/2/tutorial/floatingpoint.html#tut-fp-issuesTo rozwiązanie różni się od wszystkich innych, ponieważ:
W przypadku dowolnej liczby
n
cyfr znaczących możesz użyć:Test:
Uwaga : w przypadku tego rozwiązania nie jest możliwe dynamiczne dostosowywanie liczby cyfr znaczących na podstawie danych wejściowych, ponieważ nie ma standardowego sposobu rozróżniania liczb z różnymi liczbami końcowych zer (
3.14 == 3.1400
). Jeśli zajdzie taka potrzeba, potrzebne są niestandardowe funkcje, takie jak te zawarte w pakiecie do precyzji .źródło
:g
formatującego, który zachowuje liczby całkowite.2000.0
sugestią 5 cyfr znaczących, więc musi przejść{:g}
ponownie.) Ogólnie, liczby całkowite z zerami końcowymi są niejednoznaczne w odniesieniu do cyfr znaczących, chyba że użyta jest jakaś technika (np. Podkreślenie powyżej ostatniego znaczącego).Stworzyłem precyzyjny pakiet, który robi to, co chcesz. Pozwala na podanie liczb mniej lub bardziej znaczących.
Wyprowadza również notację standardową, naukową i inżynierską z określoną liczbą cyfr znaczących.
W zaakceptowanej odpowiedzi jest linia
To faktycznie określa 8 sig fig. Dla numeru 1234243 moja biblioteka wyświetla tylko jedną znaczącą cyfrę:
Zaokrągli również ostatnią znaczącą cyfrę i może automatycznie wybrać, jakiego zapisu użyć, jeśli notacja nie jest określona:
źródło
lambda x: to_precision(x, 2)
Aby zaokrąglić liczbę całkowitą do 1 cyfry znaczącej, podstawową ideą jest przekonwertowanie jej na liczbę zmiennoprzecinkową z 1 cyfrą przed kropką i zaokrąglić ją, a następnie przekonwertować ją z powrotem do pierwotnej wielkości całkowitej.
Aby to zrobić, musimy znać największą potęgę 10 mniejszą od liczby całkowitej. Możemy do tego użyć floor funkcji log 10.
źródło
Aby bezpośrednio odpowiedzieć na pytanie, oto moja wersja używająca nazewnictwa z funkcji R :
Moim głównym powodem opublikowania tej odpowiedzi są komentarze narzekające, że „0,075” zaokrągla do 0,07 zamiast 0,08. Wynika to, jak wskazał „Nowicjusz C”, z połączenia arytmetyki zmiennoprzecinkowej mającej zarówno skończoną precyzję, jak i reprezentację o podstawie 2 . Liczba najbliższa 0,075, którą można w rzeczywistości przedstawić, jest nieco mniejsza, dlatego zaokrąglanie wygląda inaczej, niż można by się naiwnie spodziewać.
Należy również zauważyć, że dotyczy to wszelkich zastosowań arytmetyki zmiennoprzecinkowej innej niż dziesiętna, np. C i Java mają ten sam problem.
Aby pokazać bardziej szczegółowo, prosimy Pythona o sformatowanie liczby w formacie „szesnastkowym”:
co daje nam:
0x1.3333333333333p-4
. Powodem takiego postępowania jest to, że normalna reprezentacja dziesiętna często obejmuje zaokrąglanie, a zatem nie jest to sposób, w jaki komputer faktycznie „widzi” liczbę. Jeśli nie jesteś przyzwyczajony do tego formatu, kilka przydatnych odnośników są docs Python i standard C .Aby pokazać, jak działają te liczby, możemy wrócić do punktu wyjścia, wykonując:
który powinien zostać wydrukowany
0.075
.16**13
Dzieje się tak, ponieważ po przecinku znajduje się 13 cyfr szesnastkowych, a2**-4
wykładniki szesnastkowe mają podstawę 2.Teraz mamy już pewne wyobrażenie o tym, jak reprezentowane są zmiennoprzecinkowe, możemy użyć
decimal
modułu, aby zwiększyć precyzję, pokazując nam, co się dzieje:dawanie:
0.07499999999999999722444243844
i miejmy nadzieję, że wyjaśnia, dlaczegoround(0.075, 2)
ocenia0.07
źródło
0.074999999999999999
, czego można spodziewać się w tym przypadku?Miejmy nadzieję, że biorąc pod uwagę wszystkie powyższe odpowiedzi (bez możliwości ujęcia tego jako jednowierszowej lambda;)). Jeszcze nie eksplorowałem, możesz edytować tę odpowiedź:
źródło
Zmodyfikowałem rozwiązanie indgar, aby obsługiwać liczby ujemne i małe liczby (w tym zero).
źródło
x == 0
? Jeśli kochasz jedno-liniowiec, po prostureturn 0 if x==0 else round(...)
.0.970 == 0.97
.). Myślę, że możesz użyć innych rozwiązań drukowania, na przykładf'{round_sig(0.9701, sig=3):0.3f}'
jeśli chcesz wydrukować zero.Jeśli chcesz zaokrąglić bez angażowania ciągów, link, który znalazłem ukryty w komentarzach powyżej:
http://code.activestate.com/lists/python-tutor/70739/
wydaje mi się najlepsze. Następnie, gdy drukujesz z dowolnymi deskryptorami formatowania łańcuchów, uzyskujesz rozsądny wynik i możesz użyć reprezentacji numerycznej do innych celów obliczeniowych.
Kod pod linkiem składa się z trzech linijek: def, doc i return. Ma błąd: musisz sprawdzić eksplodujące logarytmy. Tołatwe. Porównaj dane wejściowe z
sys.float_info.min
. Kompletne rozwiązanie to:Działa dla dowolnej skalarnej wartości liczbowej, a n może być a,
float
jeśli z jakiegoś powodu musisz zmienić odpowiedź. W rzeczywistości możesz przesunąć limit, aby:bez wywoływania błędu, jeśli z jakiegoś powodu pracujesz z małymi wartościami.
źródło
Nie przychodzi mi do głowy nic, co byłoby w stanie sobie z tym poradzić po wyjęciu z pudełka. Ale jest dość dobrze obsługiwany w przypadku liczb zmiennoprzecinkowych.
Liczby całkowite są trudniejsze. Nie są przechowywane jako podstawa 10 w pamięci, więc ważne miejsca nie są rzeczą naturalną. Jednak implementacja, gdy są one ciągiem, jest dość trywialna.
Lub dla liczb całkowitych:
Jeśli chcesz utworzyć funkcję obsługującą dowolną liczbę, wolałbym przekonwertować je na ciągi znaków i poszukać miejsca dziesiętnego, aby zdecydować, co zrobić:
Inną opcją jest sprawdzenie typu. Będzie to znacznie mniej elastyczne i prawdopodobnie nie będzie dobrze współgrać z innymi liczbami, takimi jak
Decimal
obiekty:źródło
Opublikowana odpowiedź była najlepszą dostępną odpowiedzią, gdy została udzielona, ale ma szereg ograniczeń i nie daje technicznie poprawnych liczb znaczących.
numpy.format_float_positional bezpośrednio obsługuje żądane zachowanie. Poniższy fragment zwraca
x
liczbę zmiennoprzecinkową sformatowaną do 4 cyfr znaczących z pominięciem notacji naukowej.źródło
print(*[''.join([np.format_float_positional(.01*a*n,precision=2,unique=False,fractional=False,trim='k',pad_right=5) for a in [.99, .999, 1.001]]) for n in [8,9,10,11,12,19,20,21]],sep='\n')
. Nie sprawdziłem samego Dragon4.Wpadłem na to również, ale potrzebowałem kontroli nad typem zaokrąglania. Dlatego napisałem szybką funkcję (patrz kod poniżej), która może brać pod uwagę wartość, typ zaokrąglenia i pożądane cyfry znaczące.
źródło
Korzystanie z formatowania w nowym stylu pythona 2.6+ (ponieważ styl% jest przestarzały):
W Pythonie 2.7+ możesz pominąć wiodące
0
s.źródło
Ta funkcja wykonuje normalną rundę, jeśli liczba jest większa niż 10 ** (- decimal_positions), w przeciwnym razie dodaje więcej miejsc dziesiętnych, aż zostanie osiągnięta liczba znaczących miejsc dziesiętnych:
Mam nadzieję, że to pomoże.
źródło
https://stackoverflow.com/users/1391441/gabriel , czy poniższe informacje dotyczą Twojego problemu dotyczącego rnd (.075, 1)? Caveat: zwraca wartość w postaci liczby zmiennoprzecinkowej
źródło
Zwraca ciąg, dzięki czemu wyniki bez części ułamkowych, a małe wartości, które w przeciwnym razie pojawiłyby się w notacji E, są wyświetlane poprawnie:
źródło
Biorąc pod uwagę tak wyczerpującą odpowiedź, dlaczego nie dodać kolejnego
To trochę lepiej pasuje do mojej estetyki, chociaż wiele z powyższych jest porównywalnych
Działa to dla pojedynczych liczb i tablic numpy i powinno działać dobrze dla liczb ujemnych.
Jest jeszcze jeden krok, który możemy dodać - np.round () zwraca liczbę dziesiętną, nawet jeśli zaokrąglona jest liczbą całkowitą (tj. Dla importantFigures = 2 możemy spodziewać się powrotu -460, ale zamiast tego otrzymamy -460.0). Możemy dodać ten krok, aby to poprawić:
Niestety, ten ostatni krok nie zadziała dla szeregu liczb - zostawię to tobie drogi czytelniku, aby dowiedzieć się, czy potrzebujesz.
źródło
Sigfig pakiet / Osłony biblioteczne to. Po zainstalowaniu możesz wykonać następujące czynności:
źródło
źródło