Odpowiedzi:
Robisz, 157/32co 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ń ai bna podwójną, a możesz użyć dzielenia i Math.ceiltak, 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 / bz zawsze wartością floor, jeśli ai bobie 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 == 0sprawdza 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 = 0i 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 < 1tak
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 plik int.
Spróbuj użyć podwójnego dosłowny - 157/32d, która jest int/double, co skutkuje double.
157/32jest dzieleniem całkowitoliczbowym, ponieważ wszystkie literały numeryczne są liczbami całkowitymi, chyba że podano inaczej z sufiksem ( ddla double lna 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ąć
double a1=157;
double a2=32;
int total = (int) Math.ceil(a1/a2);
Nikt nie wspomniał o najbardziej intuicyjnym:
int x = (int) Math.round(Math.ceil((double) 157 / 32));
To rozwiązanie naprawia niedokładność podwójnego podziału.
W Javie dodanie .0 sprawi, że będzie to podwójne ...
int total = (int) Math.ceil(157.0 / 32.0);
Dzieląc dwie liczby całkowite, np.
int c = (int) a / (int) b;
wynikiem jest an int, którego wartość jest apodzielona przez bzaokrąglenie do zera. Ponieważ wynik jest już zaokrąglony, ceil()nic nie robi. Zauważ, że to zaokrąglenie nie jest tym samym floor(), co zaokrąglenie w kierunku ujemnej nieskończoności. Więc 3/2jest równe 1(i floor(1.5)równe 1.0, ale (-3)/2równe -1(ale floor(-1.5)równe -2.0).
Jest to istotne, ponieważ jeśli a/bbyły zawsze takie same, jak floor(a / (double) b), to może po prostu wdrożyć ceil()od a/bjak -( (-a) / b).
Sugestia wyjścia ceil(a/b)z
int n = (a + b - 1) / b;, co jest równoważne z a / b + (b - 1) / blub(a - 1) / b + 1
działa, ponieważ ceil(a/b)jest zawsze o jeden większy niż floor(a/b), z wyjątkiem sytuacji, gdy a/bjest liczbą całkowitą. Więc chcesz podbić ją do (lub poza) następną liczbę całkowitą, chyba że a/bjest to liczba całkowita. Dodanie 1 - 1 / bto 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ć.
Aby przekonwertować liczbę z liczby całkowitej na liczbę rzeczywistą, możesz dodać kropkę:
int total = (int) Math.ceil(157/32.);
Wynik (157/32.) Też będzie prawdziwy. ;)
int total = (int) Math.ceil( (double)157/ (double) 32);
Java /domyślnie udostępnia tylko podział pięter . Ale możemy zapisać sufit w kategoriach podłogi . Zobaczmy:
Za ypomocą formularza można zapisać dowolną liczbę całkowitą y == q*k+r. Zgodnie z definicją podziału podłogi (tutaj floor), która zaokrągla r,
floor(q*k+r, k) == q , where 0 ≤ r ≤ k-1
i podziału sufitu (tutaj ceil), który zaokrągla w górę r₁,
ceil(q*k+r₁, k) == q+1 , where 1 ≤ r₁ ≤ k
gdzie możemy zastąpić r+1przez r₁:
ceil(q*k+r+1, k) == q+1 , where 0 ≤ r ≤ k-1
Następnie podstawiamy pierwsze równanie do trzeciego, aby quzyskać
ceil(q*k+r+1, k) == floor(q*k+r, k) + 1 , where 0 ≤ r ≤ k-1
Wreszcie, biorąc pod uwagę dowolną liczbę całkowitą y, gdzie y = q*k+r+1dla niektórych q, k, rmamy
ceil(y, k) == floor(y-1, k) + 1
Gotowe. Mam nadzieję że to pomoże.
ceiljest 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.
public class TestClass {
public static void main(String[] args) {
int floorValue = (int) Math.floor((double)157 / 32);
int ceilValue = (int) Math.ceil((double)157 / 32);
System.out.println("Floor: "+floorValue);
System.out.println("Ceil: "+ceilValue);
}
}
int total = (157-1)/32 + 1
lub bardziej ogólne
(a-1)/b +1