int total = (int) Math.ceil(157/32);
¿Por qué todavía devuelve 4? 157/32 = 4.90625
, Necesito redondear, he mirado alrededor y este parece ser el método correcto.
Intenté total
como double
tipo, pero obtuve 4.0.
¿Qué estoy haciendo mal?
Lo que está haciendo 157/32
es dividir dos enteros entre sí, lo que siempre resulta en un entero redondeado hacia abajo. Por lo tanto, (int) Math.ceil(...)
no está haciendo nada. Hay tres posibles soluciones para lograr lo que desea. Yo recomiendo usar ya sea la opción 1 o la opción 2 . Por favor, NO utilice la opción 0 .
## Opción 0
Convierta a
y b
en un doble, y puede usar la división y Math.ceil
como desea que funcione. Sin embargo, desaconsejo encarecidamente el uso de este enfoque, porque la doble división puede ser imprecisa. Para leer más sobre la imprecisión de los dobles, consulte esta pregunta .
int n = (int) Math.ceil((double) a / b));
##Opción 1
int n = a / b + ((a % b == 0) ? 0 : 1);
Lo haces a / b
con siempre suelo si a
y b
ambos son enteros. Luego tiene una instrucción if en línea que verifica si debe o no ceil en lugar de floor. Entonces +1 o +0, si hay un resto con la división, necesita +1. a % b == 0
cheques para el resto.
##Opcion 2
Esta opción es muy corta, pero quizás para algunos menos intuitivos. Creo que este enfoque menos intuitivo sería más rápido que el enfoque de doble división y comparación:
tenga en cuenta que esto no funciona b < 0
.
int n = (a + b - 1) / b;
Para reducir la posibilidad de desbordamiento, puede utilizar lo siguiente. Sin embargo, tenga en cuenta que no funciona para a = 0
y b < 1
.
int n = (a - 1) / b + 1;
## Explicación detrás del "enfoque menos intuitivo"
Dado que dividir dos enteros en Java (y la mayoría de los otros lenguajes de programación) siempre basará el resultado. Entonces:
int a, b;
int result = a/b (is the same as floor(a/b) )
Pero no queremos floor(a/b)
, pero ceil(a/b)
, y usando las definiciones y gráficos de Wikipedia :
Con estas gráficas de la función suelo y techo se puede ver la relación.
Puedes ver eso floor(x) <= ceil(x)
. Necesitamos floor(x + s) = ceil(x)
. Entonces tenemos que encontrar s
. Si lo tomamos 1/2 <= s < 1
, será correcto (pruebe algunos números y verá que sí, me resulta difícil probarlo). Y 1/2 <= (b-1) / b < 1
asi
ceil(a/b) = floor(a/b + s)
= floor(a/b + (b-1)/b)
= floor( (a+b-1)/b) )
Esta no es una prueba real, pero espero que esté satisfecho con ella. Si alguien puede explicarlo mejor, también lo agradecería. Quizás preguntarlo en MathOverflow .
157/32 es
int/int
, lo que da como resultado unint
.Intente usar el doble literal -
157/32d
, que esint/double
, que da como resultado undouble
.fuente
157/32
es una división de enteros porque todos los literales numéricos son enteros a menos que se especifique lo contrario con un sufijo (d
para doblel
para largo)la división se redondea hacia abajo (a 4) antes de convertirse en un doble (4.0) que luego se redondea hacia arriba (a 4.0)
si usa variables, puede evitarlo
fuente
fuente
Nadie ha mencionado lo más intuitivo:
Esta solución corrige la imprecisión de la doble división.
fuente
En Java, agregar un .0 lo convertirá en un doble ...
fuente
Al dividir dos enteros, por ejemplo,
int c = (int) a / (int) b;
el resultado es un
int
, cuyo valor sea
divide entreb
, redondeado hacia cero. Como el resultado ya está redondeado,ceil()
no hace nada. Tenga en cuenta que este redondeo no es el mismo quefloor()
, que redondea hacia el infinito negativo. Entonces,3/2
es igual1
(yfloor(1.5)
es igual1.0
, pero(-3)/2
es igual-1
(perofloor(-1.5)
es igual-2.0
)).Esto es importante porque si
a/b
siempre fueron los mismos quefloor(a / (double) b)
, a continuación, usted podría aplicarceil()
dea/b
tan-( (-a) / b)
.La sugerencia de obtener
ceil(a/b)
deint n = (a + b - 1) / b;
, que es equivalente aa / b + (b - 1) / b
, o(a - 1) / b + 1
funciona porque
ceil(a/b)
siempre es uno mayor quefloor(a/b)
, excepto cuandoa/b
es un número entero. Por lo tanto, desea subirlo (o pasar) al siguiente número entero, a menos quea/b
sea un número entero. Agregar1 - 1 / b
hará esto. Para números enteros, no los empujará al siguiente número entero. Para todo lo demás, lo hará.¡Ay! Ojalá tenga sentido. Estoy seguro de que hay una forma matemáticamente más elegante de explicarlo.
fuente
Además, para convertir un número de entero a número real, puede agregar un punto:
Y el resultado de (157/32.) También será real. ;)
fuente
fuente
Compruebe la solución a continuación para su pregunta:
Aquí debe multiplicar Numerador por 1.0, luego dará su respuesta.
fuente
Usa doble para lanzar como
Math.ceil((double)value)
o me gustafuente
Java proporciona solo división de piso
/
de forma predeterminada. Pero podemos escribir techo en términos de piso . Veamos:Cualquier número entero
y
se puede escribir con el formularioy == q*k+r
. De acuerdo con la definición de división de piso (aquífloor
) que completar
,y de la división del techo (aquí
ceil
) que se redondear₁
,donde podemos sustituir
r+1
porr₁
:Luego sustituimos la primera ecuación en la tercera para
q
obtenerPor último, dado cualquier número entero
y
, dondey = q*k+r+1
para algunosq
,k
,r
, tenemosY hemos terminado. Espero que esto ayude.
fuente
ceil
queda claro por qué se define como tal a partir de la definición intuitiva, en particular cuando estamos tomando el techo de un número entero, es decir, r1 = k. Dado que los casos extremos son lo complicado de esto, creo que debe explicarse un poco más.Hay dos métodos mediante los cuales puede redondear su valor doble.
Si desea que su respuesta 4.90625 sea 4, entonces debe usar Math.floor y si desea que su respuesta 4.90625 sea 5, entonces puede usar Math.ceil
Puede consultar el siguiente código para eso.
fuente
o más general
fuente