Respostas:
Você está fazendo o 157/32
que é dividir dois inteiros entre si, o que sempre resulta em um inteiro arredondado para baixo. Portanto, o (int) Math.ceil(...)
não está fazendo nada. Existem três soluções possíveis para alcançar o que deseja. Eu recomendo usar a opção 1 ou a opção 2 . Por favor, não use a opção 0 .
## Opção 0
Converta a
e b
para um duplo, e você pode usar a divisão e Math.ceil
como você queria que funcionasse. No entanto, eu desencorajo fortemente o uso dessa abordagem, porque a divisão dupla pode ser imprecisa. Para ler mais sobre a imprecisão das duplas, consulte esta questão .
int n = (int) Math.ceil((double) a / b));
##Opção 1
int n = a / b + ((a % b == 0) ? 0 : 1);
Você faz a / b
com always floor se a
e b
forem ambos inteiros. Então você tem uma instrução if inline que verifica se você deve ou não teto em vez de chão. Portanto, +1 ou +0, se houver um resto com a divisão, você precisará de +1. a % b == 0
verifica o restante.
##Opção 2
Esta opção é muito curta, mas talvez para alguns menos intuitiva. Acho que essa abordagem menos intuitiva seria mais rápida do que a abordagem de divisão dupla e comparação:
Observe que isso não funciona para b < 0
.
int n = (a + b - 1) / b;
Para reduzir a chance de estouro, você pode usar o seguinte. No entanto, observe que não funciona para a = 0
e b < 1
.
int n = (a - 1) / b + 1;
## Explicação por trás da "abordagem menos intuitiva"
Uma vez que dividir dois inteiros em Java (e na maioria das outras linguagens de programação) sempre irá limitar o resultado. Assim:
int a, b;
int result = a/b (is the same as floor(a/b) )
Mas não queremos floor(a/b)
, mas ceil(a/b)
e usando as definições e gráficos da Wikipedia :
Com estes lotes da função chão e tecto é possível ver a relação.
Você pode ver isso floor(x) <= ceil(x)
. Nós precisamos floor(x + s) = ceil(x)
. Portanto, precisamos encontrar s
. Se pegarmos 1/2 <= s < 1
, vai dar certo (experimente alguns números e você verá que sim, eu mesmo acho difícil provar isso). E 1/2 <= (b-1) / b < 1
então
ceil(a/b) = floor(a/b + s)
= floor(a/b + (b-1)/b)
= floor( (a+b-1)/b) )
Esta não é uma prova real, mas espero que você esteja satisfeito com ela. Se alguém puder explicar melhor eu também agradeceria. Talvez pergunte no MathOverflow .
157/32 é int/int
, o que resulta em um int
.
Tente usar o literal dupla - 157/32d
, o que é int/double
, o que resulta em um double
.
157/32
é uma divisão inteira porque todos os literais numéricos são inteiros, a menos que seja especificado de outra forma com um sufixo ( d
para double l
for long)
a divisão é arredondada para baixo (para 4) antes de ser convertida para um duplo (4,0), que é então arredondado para cima (para 4,0)
se você usar variáveis, pode evitar que
double a1=157;
double a2=32;
int total = (int) Math.ceil(a1/a2);
Ninguém mencionou o mais intuitivo:
int x = (int) Math.round(Math.ceil((double) 157 / 32));
Esta solução corrige a imprecisão da divisão dupla .
Em Java, adicionar um .0 tornará um duplo ...
int total = (int) Math.ceil(157.0 / 32.0);
Ao dividir dois inteiros, por exemplo,
int c = (int) a / (int) b;
o resultado é um int
, o valor do qual é a
dividido por b
, arredondado para zero. Porque o resultado já está arredondado, ceil()
não faz nada. Observe que esse arredondamento não é o mesmo que floor()
, que arredonda para o infinito negativo. Então, 3/2
igual 1
(e floor(1.5)
igual 1.0
, mas (-3)/2
igual -1
(mas floor(-1.5)
igual -2.0
).
Isso é significativo porque se a/b
fosse sempre o mesmo que floor(a / (double) b)
, você poderia apenas implementar ceil()
de a/b
como -( (-a) / b)
.
A sugestão de obter ceil(a/b)
de
int n = (a + b - 1) / b;
, que é equivalente a a / b + (b - 1) / b
, ou(a - 1) / b + 1
funciona porque ceil(a/b)
é sempre um maior que floor(a/b)
, exceto quando a/b
é um número inteiro. Portanto, você deseja aumentar (ou ultrapassar) o próximo número inteiro, a menos que a/b
seja um número inteiro. Adicionar 1 - 1 / b
fará isso. Para números inteiros, não vai empurrá-los para o próximo número inteiro. Para todo o resto, sim.
Caramba. Esperançosamente, isso faz sentido. Tenho certeza de que há uma maneira matematicamente mais elegante de explicar isso.
Além disso, para converter um número inteiro em real, você pode adicionar um ponto:
int total = (int) Math.ceil(157/32.);
E o resultado de (157/32.) Também será real. ;)
Verifique a solução abaixo para sua dúvida:
int total = (int) Math.ceil(157/32);
Aqui você deve multiplicar Numerator por 1.0, então ele dará sua resposta.
int total = (int) Math.ceil(157*1.0/32);
Java fornece apenas divisão de piso /
por padrão. Mas podemos escrever teto em termos de piso . Vamos ver:
Qualquer número inteiro y
pode ser escrito com o formulário y == q*k+r
. De acordo com a definição de divisão do piso (aqui floor
) que completa r
,
floor(q*k+r, k) == q , where 0 ≤ r ≤ k-1
e da divisão do teto (aqui ceil
) que arredonda para cima r₁
,
ceil(q*k+r₁, k) == q+1 , where 1 ≤ r₁ ≤ k
onde podemos substituir r+1
por r₁
:
ceil(q*k+r+1, k) == q+1 , where 0 ≤ r ≤ k-1
Em seguida, substituímos a primeira equação na terceira para q
obter
ceil(q*k+r+1, k) == floor(q*k+r, k) + 1 , where 0 ≤ r ≤ k-1
Finalmente, dado qualquer inteiro y
onde y = q*k+r+1
há algum q
, k
, r
, temos
ceil(y, k) == floor(y-1, k) + 1
E nós terminamos. Espero que isto ajude.
ceil
é definido como tal na definição intuitiva, em particular quando estamos tomando o teto de um número inteiro, ou seja, r1 = k. Já que os casos extremos são o que há de complicado nisso, acho que precisa ser explicado um pouco mais.
Existem dois métodos pelos quais você pode arredondar o seu valor duplo.
Se você quiser sua resposta 4,90625 como 4, você deve usar Math.floor e se você quiser sua resposta 4,90625 como 5, você pode usar Math.ceil
Você pode consultar o código a seguir para isso.
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
ou mais geral
(a-1)/b +1