int total = (int) Math.ceil(157/32);
Dlaczego nadal zwraca 4? 157/32 = 4.90625
, Muszę zaokrąglić, rozejrzałem się i wydaje mi się, że to właściwa metoda.
Próbowałem total
jako double
typ, ale otrzymałem 4.0.
Co ja robię źle?
Robisz, 157/32
co polega na dzieleniu między sobą dwóch liczb całkowitych, co zawsze skutkuje zaokrągleniem w dół. Dlatego (int) Math.ceil(...)
nic nie robi. Istnieją trzy możliwe rozwiązania, aby osiągnąć to, czego chcesz. I zalecają przy użyciu opcji 1 lub opcji 2 . Proszę nie NIE używać opcji 0 .
## Opcja 0
Zamień a
i b
na podwójną, a możesz użyć dzielenia i Math.ceil
tak, jak chciałeś, aby działał. Jednak zdecydowanie odradzam stosowanie tego podejścia, ponieważ podwójny podział może być nieprecyzyjny. Aby dowiedzieć się więcej na temat nieprecyzyjności podwójnych, zobacz to pytanie .
int n = (int) Math.ceil((double) a / b));
##Opcja 1
int n = a / b + ((a % b == 0) ? 0 : 1);
Robisz a / b
z zawsze wartością floor, jeśli a
i b
obie są liczbami całkowitymi. Następnie masz wbudowane oświadczenie `` jeśli '', które sprawdza, czy zamiast podłogi należy ustawić sufit. Więc +1 lub +0, jeśli jest reszta z dzielenia, potrzebujesz +1. a % b == 0
sprawdza pozostałą część.
##Opcja 2
Ta opcja jest bardzo krótka, ale może dla niektórych mniej intuicyjna. Myślę, że to mniej intuicyjne podejście byłoby szybsze niż podejście z podwójnym dzieleniem i porównaniem:
proszę zauważyć, że to nie działa b < 0
.
int n = (a + b - 1) / b;
Aby zmniejszyć ryzyko przepełnienia, możesz użyć następującego. Należy jednak pamiętać, że nie działa w przypadku a = 0
i b < 1
.
int n = (a - 1) / b + 1;
## Wyjaśnienie „mniej intuicyjnego podejścia”
Ponieważ dzielenie dwóch liczb całkowitych w Javie (i większości innych języków programowania) zawsze będzie skutkowało wynikiem. Więc:
int a, b;
int result = a/b (is the same as floor(a/b) )
Ale nie chcemy floor(a/b)
, ale ceil(a/b)
i używając definicji i wykresów z Wikipedii :
Dzięki tym działkom funkcji podłogi i sufitu można zobaczyć związek.
Możesz to zobaczyć floor(x) <= ceil(x)
. Potrzebujemy floor(x + s) = ceil(x)
. Więc musimy znaleźć s
. Jeśli weźmiemy pod uwagę 1/2 <= s < 1
, będzie dobrze (spróbuj kilku liczb, a zobaczysz, że tak, trudno mi to udowodnić). I 1/2 <= (b-1) / b < 1
tak
ceil(a/b) = floor(a/b + s)
= floor(a/b + (b-1)/b)
= floor( (a+b-1)/b) )
To nie jest prawdziwy dowód, ale mam nadzieję, że jesteś z niego zadowolony. Gdyby ktoś mógł to lepiej wytłumaczyć, też bym to docenił. Może zapytaj o to w MathOverflow .
157/32 jest
int/int
, co powoduje, że plikint
.Spróbuj użyć podwójnego dosłowny -
157/32d
, która jestint/double
, co skutkujedouble
.źródło
157/32
jest dzieleniem całkowitoliczbowym, ponieważ wszystkie literały numeryczne są liczbami całkowitymi, chyba że podano inaczej z sufiksem (d
dla doublel
na długo)podział jest zaokrąglany w dół (do 4) przed zamianą na podwójny (4,0), który jest następnie zaokrąglany w górę (do 4,0)
jeśli używasz zmiennych, możesz tego uniknąć
źródło
źródło
Nikt nie wspomniał o najbardziej intuicyjnym:
To rozwiązanie naprawia niedokładność podwójnego podziału.
źródło
W Javie dodanie .0 sprawi, że będzie to podwójne ...
źródło
Dzieląc dwie liczby całkowite, np.
int c = (int) a / (int) b;
wynikiem jest an
int
, którego wartość jesta
podzielona przezb
zaokrąglenie do zera. Ponieważ wynik jest już zaokrąglony,ceil()
nic nie robi. Zauważ, że to zaokrąglenie nie jest tym samymfloor()
, co zaokrąglenie w kierunku ujemnej nieskończoności. Więc3/2
jest równe1
(ifloor(1.5)
równe1.0
, ale(-3)/2
równe-1
(alefloor(-1.5)
równe-2.0
).Jest to istotne, ponieważ jeśli
a/b
były zawsze takie same, jakfloor(a / (double) b)
, to może po prostu wdrożyćceil()
oda/b
jak-( (-a) / b)
.Sugestia wyjścia
ceil(a/b)
zint n = (a + b - 1) / b;
, co jest równoważne za / b + (b - 1) / b
lub(a - 1) / b + 1
działa, ponieważ
ceil(a/b)
jest zawsze o jeden większy niżfloor(a/b)
, z wyjątkiem sytuacji, gdya/b
jest liczbą całkowitą. Więc chcesz podbić ją do (lub poza) następną liczbę całkowitą, chyba żea/b
jest to liczba całkowita. Dodanie1 - 1 / b
to zrobi. W przypadku liczb całkowitych nie przesunie ich do następnej liczby całkowitej. W przypadku wszystkiego innego tak będzie.Yikes. Mam nadzieję, że to ma sens. Jestem pewien, że istnieje bardziej matematycznie elegancki sposób, aby to wyjaśnić.
źródło
Aby przekonwertować liczbę z liczby całkowitej na liczbę rzeczywistą, możesz dodać kropkę:
Wynik (157/32.) Też będzie prawdziwy. ;)
źródło
źródło
Sprawdź poniższe rozwiązanie dla swojego pytania:
Tutaj powinieneś pomnożyć Licznik przez 1.0, wtedy poda twoją odpowiedź.
źródło
Użyj podwójnego, aby rzucać jak
Math.ceil((double)value)
lub jakźródło
Java
/
domyślnie udostępnia tylko podział pięter . Ale możemy zapisać sufit w kategoriach podłogi . Zobaczmy:Za
y
pomocą formularza można zapisać dowolną liczbę całkowitąy == q*k+r
. Zgodnie z definicją podziału podłogi (tutajfloor
), która zaokrąglar
,i podziału sufitu (tutaj
ceil
), który zaokrągla w góręr₁
,gdzie możemy zastąpić
r+1
przezr₁
:Następnie podstawiamy pierwsze równanie do trzeciego, aby
q
uzyskaćWreszcie, biorąc pod uwagę dowolną liczbę całkowitą
y
, gdziey = q*k+r+1
dla niektórychq
,k
,r
mamyGotowe. Mam nadzieję że to pomoże.
źródło
ceil
jest definiowany jako taki na podstawie definicji intiuywnej, w szczególności, gdy bierzemy górną granicę liczby całkowitej, tj. R1 = k. Ponieważ przypadki skrajne są tym, co jest w tym trudne, myślę, że należy to nieco dokładniej opisać.Są dwie metody zaokrąglania podwójnej wartości.
Jeśli chcesz uzyskać odpowiedź 4.90625 jako 4, powinieneś użyć Math.floor, a jeśli chcesz uzyskać odpowiedź 4.90625 jako 5, możesz użyć Math.ceil
Możesz skorzystać z następującego kodu.
źródło
lub bardziej ogólne
źródło