Jak zaokrąglić dowolną liczbę (nie tylko liczby całkowite> 0) do N cyfr znaczących?
Na przykład, jeśli chcę zaokrąglić do trzech cyfr znaczących, szukam formuły, która mogłaby przyjąć:
1 239 451 i zwraca 1 240 000
12.1257 i powrót 12.1
.0681 i zwraca .0681
5 i wróć 5
Naturalnie algorytm nie powinien być zakodowany na stałe tak, aby obsługiwał tylko N z 3, chociaż byłby to początek.
Odpowiedzi:
Oto ten sam kod w Javie bez błędu 12.100000000000001, który mają inne odpowiedzi
Usunąłem również powtarzający się kod, zmieniłem
power
na typ całkowity, aby zapobiec problemom związanym z pływaniem pon - d
zakończeniu, i uczyniłem długi pośredni bardziej przejrzystymBłąd był spowodowany pomnożeniem dużej liczby przez małą. Zamiast tego dzielę dwie liczby o podobnej wielkości.
EDYCJA
Naprawiono więcej błędów. Dodano czek na 0, ponieważ spowodowałoby to NaN. Sprawiono, że funkcja faktycznie działa z liczbami ujemnymi (oryginalny kod nie obsługuje liczb ujemnych, ponieważ dziennik liczb ujemnych jest liczbą zespoloną)
źródło
Oto krótka i słodka implementacja JavaScript:
źródło
n==0
:)Math.log(n) / Math.LN10
a nieMath.log10(n)
?Math.floor(x) == Math.ceil(x) - 1
? Ponieważ tak niex
jest, gdy jest liczbą całkowitą. Myślę, że drugim argumentempow
funkcji powinien byćsig - Math.ceil(Math.log(n) / Math.LN10)
(lub po prostu użyjMath.log10
)PODSUMOWANIE:
Musisz więc znaleźć miejsce dziesiętne pierwszej niezerowej cyfry, a następnie zapisać następne N-1 cyfry, a następnie zaokrąglić N-tą cyfrę na podstawie reszty.
Możemy użyć dziennika, aby zrobić pierwszy.
Więc dla liczb> 0, weź górną część dziennika. W przypadku liczb <0 zajmij podłogę dziennika.
Teraz mamy cyfrę
d
: 7 w pierwszym przypadku, 2 w drugim, -2 w trzecim.Musimy zaokrąglić tę
(d-N)
cyfrę. Coś jak:Następnie wykonaj standardowe zaokrąglenie:
I cofnij pow.
Gdzie moc to moc obliczona powyżej.
O dokładności: odpowiedź pirolisty jest rzeczywiście bliższa rzeczywistemu wynikowi. Ale pamiętaj, że w żadnym wypadku nie możesz dokładnie reprezentować 12.1. Jeśli wydrukujesz odpowiedzi w następujący sposób:
Odpowiedzi są następujące:
A więc użyj odpowiedzi Pyro!
źródło
Czy to nie „krótka i słodka” implementacja JavaScript
na przykład
?
Przepraszam, nie żartuję, po prostu użycie funkcji „roundit” z Claudiu i .toPrecision w JavaScript daje mi różne wyniki, ale tylko w zaokrągleniu ostatniej cyfry.
JavaScript:
.NETTO
źródło
Number(814301).toPrecision(4) == "8.143e+5"
. Generalnie nie to, czego chcesz, jeśli pokazujesz to użytkownikom.Rozwiązanie pirolistyczne (bardzo ładne!) Wciąż zawiera problem. Maksymalna podwójna wartość w Javie jest rzędu 10 ^ 308, podczas gdy minimalna jest rzędu 10 ^ -324. Dlatego możesz wpaść w kłopoty, stosując funkcję
roundToSignificantFigures
do czegoś, co znajduje się w granicach kilku potęg dziesięciuDouble.MIN_VALUE
. Na przykład, kiedy dzwoniszwtedy zmienna
power
będzie miała wartość 3 - (-309) = 312. W konsekwencji zmiennamagnitude
stanie sięInfinity
i odtąd wszystko będzie śmieciem. Na szczęście nie jest to problem nie do pokonania: to tylko czynnik,magnitude
który przepełnia. Tak naprawdę liczy się produktnum * magnitude
, który się nie przepełnia. Jednym ze sposobów rozwiązania tego problemu jest podzielenie mnożenia przez współczynnikmagintude
na dwa etapy:źródło
Co powiesz na to rozwiązanie Java:
źródło
Oto zmodyfikowana wersja JavaScript firmy Ates, która obsługuje liczby ujemne.
źródło
Spóźniło się to 5 lat, ale podzielę się tym, aby inni nadal mieli ten sam problem. Podoba mi się to, ponieważ jest proste i nie ma obliczeń po stronie kodu. Aby uzyskać więcej informacji, zobacz Wbudowane metody wyświetlania liczb znaczących .
Dzieje się tak, jeśli chcesz go po prostu wydrukować.
To jest, jeśli chcesz go przekonwertować:
Oto przykład tego w akcji:
źródło
JavaScript:
Number
Funkcja zmieni wyjście postaci"8.143e+5"
do"814300"
.źródło
Czy próbowałeś po prostu zakodować to tak, jak zrobiłbyś to ręcznie?
źródło
[Poprawiono, 2009-10-26]
Zasadniczo dla N znaczących cyfr ułamkowych :
• Pomnóż liczbę przez 10 N
• Dodaj 0,5
• Obetnij cyfry ułamkowe (tj. Skróć wynik do liczby całkowitej)
• Podziel przez 10 N
Dla N znaczących cyfr całkowitych (nieułamkowych):
• Podziel liczbę przez 10 N
• Dodaj 0,5
• Obetnij cyfry ułamkowe (tj. Skróć wynik do liczby całkowitej)
• Pomnóż przez 10 N
Możesz to zrobić na dowolnym kalkulatorze, na przykład, który ma operator „INT” (obcięcie liczby całkowitej).
źródło
źródło
Oto kod Pyrolistics (obecnie najlepsza odpowiedź) w Visual Basic.NET, gdyby ktoś go potrzebował:
źródło
Oto ten, który wymyśliłem w VB:
źródło
return new BigDecimal(value, new MathContext(significantFigures, RoundingMode.HALF_UP)).doubleValue();
źródło
Potrzebowałem tego w Go, co było nieco skomplikowane przez brak standardowej biblioteki Go
math.Round()
(przed go1.10). Więc musiałem to też podnieść. Oto moje tłumaczenie doskonałej odpowiedzi Pyrolisticsa :źródło
Możesz uniknąć wykonywania wszystkich tych obliczeń z potęgami 10 itd., Używając po prostu FloatToStrF.
FloatToStrF umożliwia (między innymi) wybranie dokładności (liczby cyfr znaczących) wartości wyjściowej (która będzie ciągiem znaków). Oczywiście możesz następnie zastosować do tego StrToFloat, aby uzyskać zaokrągloną wartość jako zmiennoprzecinkową.
Spójrz tutaj:
http://docs.embarcadero.com/products/rad_studio/delphiAndcpp2009/HelpUpdate2/EN/html/delphivclwin32/SysUtils_FloatToStrF@Extended@TFloatFormat@[email protected]
źródło
Ten kod używa wbudowanej funkcji formatowania, która została zamieniona na funkcję zaokrąglania
źródło