Odpowiedzi:
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 plik int
.
Spróbuj użyć podwójnego dosłowny - 157/32d
, która jest int/double
, co skutkuje double
.
157/32
jest dzieleniem całkowitoliczbowym, ponieważ wszystkie literały numeryczne są liczbami całkowitymi, chyba że podano inaczej z sufiksem ( d
dla double l
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ąć
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 a
podzielona przez b
zaokrą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/2
jest równe 1
(i floor(1.5)
równe 1.0
, ale (-3)/2
równe -1
(ale floor(-1.5)
równe -2.0
).
Jest to istotne, ponieważ jeśli a/b
były zawsze takie same, jak floor(a / (double) b)
, to może po prostu wdrożyć ceil()
od a/b
jak -( (-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) / 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, gdy a/b
jest liczbą całkowitą. Więc chcesz podbić ją do (lub poza) następną liczbę całkowitą, chyba że a/b
jest to liczba całkowita. Dodanie 1 - 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ć.
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 y
pomocą 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+1
przez r₁
:
ceil(q*k+r+1, k) == q+1 , where 0 ≤ r ≤ k-1
Następnie podstawiamy pierwsze równanie do trzeciego, aby q
uzyskać
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+1
dla niektórych q
, k
, r
mamy
ceil(y, k) == floor(y-1, k) + 1
Gotowe. Mam nadzieję że to pomoże.
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.
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