int total = (int) Math.ceil(157/32);
Por que ainda retorna 4? 157/32 = 4.90625
, Preciso arredondar, olhei em volta e parece ser o método certo.
Tentei total
como double
tipo, mas consegui 4.0.
O que estou fazendo de errado?
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 umint
.Tente usar o literal dupla -
157/32d
, o que éint/double
, o que resulta em umdouble
.fonte
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 doublel
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
fonte
fonte
Ninguém mencionou o mais intuitivo:
Esta solução corrige a imprecisão da divisão dupla .
fonte
Em Java, adicionar um .0 tornará um duplo ...
fonte
Ao dividir dois inteiros, por exemplo,
int c = (int) a / (int) b;
o resultado é um
int
, o valor do qual éa
dividido porb
, arredondado para zero. Porque o resultado já está arredondado,ceil()
não faz nada. Observe que esse arredondamento não é o mesmo quefloor()
, que arredonda para o infinito negativo. Então,3/2
igual1
(efloor(1.5)
igual1.0
, mas(-3)/2
igual-1
(masfloor(-1.5)
igual-2.0
).Isso é significativo porque se
a/b
fosse sempre o mesmo quefloor(a / (double) b)
, você poderia apenas implementarceil()
dea/b
como-( (-a) / b)
.A sugestão de obter
ceil(a/b)
deint n = (a + b - 1) / b;
, que é equivalente aa / b + (b - 1) / b
, ou(a - 1) / b + 1
funciona porque
ceil(a/b)
é sempre um maior quefloor(a/b)
, exceto quandoa/b
é um número inteiro. Portanto, você deseja aumentar (ou ultrapassar) o próximo número inteiro, a menos quea/b
seja um número inteiro. Adicionar1 - 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.
fonte
Além disso, para converter um número inteiro em real, você pode adicionar um ponto:
E o resultado de (157/32.) Também será real. ;)
fonte
fonte
Verifique a solução abaixo para sua dúvida:
Aqui você deve multiplicar Numerator por 1.0, então ele dará sua resposta.
fonte
Use duplo para lançar como
Math.ceil((double)value)
ou comofonte
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árioy == q*k+r
. De acordo com a definição de divisão do piso (aquifloor
) que completar
,e da divisão do teto (aqui
ceil
) que arredonda para cimar₁
,onde podemos substituir
r+1
porr₁
:Em seguida, substituímos a primeira equação na terceira para
q
obterFinalmente, dado qualquer inteiro
y
ondey = q*k+r+1
há algumq
,k
,r
, temosE nós terminamos. Espero que isto ajude.
fonte
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.
fonte
ou mais geral
fonte