Satysfakcjonujące zaokrąglanie
Wiesz, kiedy jesteś w klasie naukowej i poprosiłeś o zaokrąglenie do 2 sig fig, ale twoja odpowiedź brzmi 5.2501...
? Powinieneś zaokrąglić do 5.3
, ale to po prostu takie niezadowalające! Zaokrąglając do 5.3
, otrzymujesz całe 0,05, co stanowi dużą kwotę w porównaniu do 0,1 (wartość miejsca, do której zaokrąglasz)! Pomóż mi więc w satysfakcjonujący sposób.
Aby zaokrąglić w sposób satysfakcjonujący, należy zaokrąglić pierwszą napotkaną cyfrę, która powoduje stosunkowo mały błąd - mniej niż połowę maksymalnego błędu możliwego podczas zaokrąglania. Zasadniczo musisz zaokrąglać za każdym razem, gdy napotkasz 0, 1, 8 lub 9. Jeśli to się nigdy nie zdarzy, zwróć dane wejściowe bez zmian. Nie zaokrąglaj wiodących zer lub jedynek - to po prostu nie jest satysfakcjonujące.
Wejście
Ciąg lub wartość zmiennoprzecinkowa reprezentująca nieujemną liczbę dziesiętną.
Wynik
Ta sama liczba dziesiętna zaokrąglona w sposób zadowalający, zarówno w formacie ciągowym, jak i zmiennoprzecinkowym.
Przykłady
Input -> Output
0 -> 0
0.5 -> 0.5
0.19 -> 0
0.8 -> 1
5.64511 -> 5.645
18.913 -> 20
88.913 -> 100
36.38299 -> 36.4
621 -> 620
803.22 -> 1000
547.4726 -> 547.4726
To wyzwanie dla golfa , więc wygrywa najkrótszy kod!
źródło
036.40000
uważane za prawidłowe dane wyjściowe?.0
część zostanie podana dla liczb całkowitych? Również0
nie jest pozytywne.19
zaokrągla do,20
ale0.19
zaokrągla do0
? Dlaczego?Odpowiedzi:
JavaScript (ES6),
100 99 9878 bajtówPobiera dane wejściowe jako ciąg. Zwraca liczbę zmiennoprzecinkową.
Wypróbuj online!
W jaki sposób?
Najpierw wstawiamy wiodące0 do ciągu wejściowego, aby zagwarantować, że będziemy mieć cyfrę przed możliwym początkowym 8 lub 9 , która musi natychmiast uruchomić zaokrąglanie.
Flagaj jest ustawiona na 1 dopóki szukamy cyfry, na której możemy wykonać satysfakcjonujące zaokrąglenie, i ustawiona na0 .
Ponieważ wiodące0 zostało dodane do ciągu, przez który przechodzimy, ale s pozostało niezmienione, d zawiera bieżący znak s[i] wskazuje na następny znak.
Używamy następującego kodu, aby załadować następną cyfrę wn , pomijając ewentualny separator dziesiętny:
Chociaż ciągi znaków są niezmienne w JavaScript, wyrażenies[i]+1 jeśli zawiera wartość liczbową, nawet jeśli s[i] nie jest w rzeczywistości zwiększany. Dlatego wyrażenie false (wymuszone na 0 ) dla wszystkich cyfr (w tym 0 ) i na true (wymuszone na 1 ) dla separatora dziesiętnego
++s[i]
zwróci!++s[i]
jest oceniane na"."
.Kiedy następuje zaokrąglenie, dajemy,n wynosi 0 lub 1 (i nie jest to cyfra wiodąca oryginalnego wejścia) i n wynosi 8 lub 9 . Dlatego j jest ustawione na 0 w obu przypadkach, ale dodajemy 0 do d w pierwszym przypadku (zaokrąglanie w dół) i 1 w drugim przypadku (zaokrąglanie w górę).
d + --j
jeśli następna cyfrad + j--
jeśliźródło
Ruby ,
7977696765 bajtówWypróbuj online!
Wyjaśnienie
->n
Weź dane jako ciągz=n+".0"
Utwórz tymczasowy ciągz
który ma gwarantowaną kropkę i odpowiednią cyfrę.i=z=~/\./
Określ pozycję kropki dziesiętnejz
i przypisz doi
.z[i]=''
Upuść kropkę, aby nie przeszkadzała.z=~/(?!^)[01]|8|9/
Określenie pozycji nie wychodząc0-1
lub dowolny8-9
, w zależności od tego, co nastąpi wcześniej.(...)-i
Ta różnica będzie liczbą miejsc dziesiętnych, które należy zachować, ujemną, jeśli będziemy zaokrąglać po lewej stronie kropki.n.to_f.round ...
Konwertuj na float i wykonaj zaokrąglanie.źródło
Galaretka , 34 bajty
Wypróbuj online!
-1 dzięki Jonathanowi Allanowi .
źródło
ŒV
? Myślę, żeV
też zadziała._>¥0ɓVær
jak moje (brakowało mi używania dynamicznego, więc też dzięki!)Galaretka ,
3029 bajtów-1 dzięki Erikowi Outgolfer (użycie diademu szybko
¥
z jego odpowiedzi)Monadyczny link akceptujący listę znaków, który daje liczbę zmiennoprzecinkową.
Wypróbuj online! Lub zobacz pakiet testowy .
W jaki sposób
Po pierwsze zauważ, że łańcuch wejściowy składa się wyłącznie z znaków,
0123456789.
które mają liczby porządkowe[48,49,50,51,52,53,54,55,56,57,46]
, które mają reszty po podzieleniu przez osiem z[0,1,2,3,4,5,6,7,0,1,6]
. Jedyne znaki, które są pomiędzy-1
i1
włącznie są0
,1
,8
, i9
.Ponadto, jeśli odejmiemy osiem od rzędnych (
[40,41,42,43,44,45,46,47,48,49,38]
), zachowa się to samo (dość oczywiste). Jeśli[20,20.5,21,21.5,22,22.5,23,23.5,24,24.5,19]
podzielimy je na pół ( ), jedynymi znakami, które mają reszty, gdy zostaną podzielone przez osiem, które są pomiędzy-1
i1
włącznie, są8
i9
.źródło
Retina 0.8.2 , 75 bajtów
Wypróbuj online! Link zawiera przypadki testowe. Wyjaśnienie:
Obsługiwać przypadek wiodącego
8
lub9
.Jeśli jest nieprzewodzący
0
lub1
, wyzeruj go i resztę ciągu. Ponadto, jeśli istnieje znak „8
lub”9
, pozostaw go, ale wyzeruj resztę ciągu. (Ale w każdym przypadku pozostaw kropkę dziesiętną bez zmian).Jeśli w tym miejscu nadal jest cyfra
8
lub a9
, wyzeruj ją i zwiększ poprzednią cyfrę (być może przed kropką dziesiętną).Usuń końcowe zera, jeśli występują po przecinku, ale usuń przecinek tylko wtedy, gdy nie ma między nimi żadnych innych cyfr.
źródło
C (gcc) ,
111102 bajtówWypróbuj online!
źródło
C # (interaktywny kompilator Visual C #) , 280 bajtów
Wypróbuj online!
Może być krótszy, jeśli użyłem podwójnych zamiast dziesiętnych, ale użyłem dziesiętnych dla zachowania dokładności, w przeciwnym razie liczba taka jak 547,4726 byłaby 547.472595214844.
C # (interaktywny kompilator Visual C #) , 268 bajtów
Wypróbuj online! (Mniej dokładna wersja)
źródło