web-dev-qa-db-fra.com

Java arrondi à un int utilisant Math.ceil

int total = (int) Math.ceil(157/32);

Pourquoi retourne-t-il toujours 4? 157/32 = 4.90625, J'ai besoin de rassembler, j'ai regardé autour et cela semble être la bonne méthode.

J'ai essayé total comme double tapez, mais obtenez 4.0.

Qu'est-ce que je fais mal?

89
tom

Vous faites 157/32 Qui divise deux entiers, ce qui donne toujours un entier arrondi. Par conséquent, le (int) Math.ceil(...) Ne fait rien. Il existe trois solutions possibles pour réaliser ce que vous voulez. Je recommande en utilisant soit l'option 1 ou option 2 . Veuillez faire [~ # ~] pas [~ # ~] utiliser l'option 0 .

Option 0

Convertissez a et b en double et vous pouvez utiliser la division et Math.ceil Comme vous le souhaitez. Cependant, je déconseille fortement l’utilisation de cette approche, car la double division peut être imprécise. Pour en savoir plus sur l'imprécision des doublons, voir cette question .

int n = (int) Math.ceil((double) a / b));

Option 1

int n = a / b + ((a % b == 0) ? 0 : 1); 

Vous faites a / b Avec toujours floor si a et b sont tous deux des entiers. Ensuite, vous avez une déclaration if en ligne qui vérifie si vous devez ou non plafonner au lieu de sol. Donc +1 ou +0, s'il y a un reste avec la division dont vous avez besoin de +1. a % b == 0 Vérifie le reste.

Option 2

Cette option est très courte, mais peut-être moins intuitive. Je pense que cette approche moins intuitive serait plus rapide que la méthode de la double division et de la comparaison:

int n = (a + b - 1) / b;

Pour réduire les risques de débordement, vous pouvez utiliser ce qui suit. Cependant, veuillez noter que cela ne fonctionne pas pour a = 0 Et b < 1.

int n = (a - 1) / b + 1;

Explication derrière "l'approche moins intuitive"

Depuis la division de deux nombres entiers dans Java (et la plupart des autres langages de programmation)) aura toujours le résultat final.

int a, b;
int result = a/b (is the same as floor(a/b) )

Mais nous ne voulons pas de floor(a/b), mais de ceil(a/b), et en utilisant les définitions et les graphes de Wikipediaenter image description here

Avec ces graphiques de la fonction sol et plafond, vous pouvez voir la relation.

Floor functionCeil function

Vous pouvez voir que floor(x) <= ceil(x). Nous avons besoin de floor(x + s) = ceil(x). Il faut donc trouver s. Si nous prenons 1/2 <= s < 1, Ce sera parfait (essayez quelques chiffres et vous verrez que oui, j'ai du mal à le prouver). Et 1/2 <= (b-1) / b < 1, donc

ceil(a/b) = floor(a/b + s)
          = floor(a/b + (b-1)/b)
          = floor( (a+b-1)/b) )

Ce n'est pas une vraie preuve, mais j'espère que vous en êtes satisfait. Si quelqu'un peut mieux l'expliquer, je l'apprécierais aussi. Peut-être le demander sur MathOverflow .

166
martijnn2008

157/32 est int/int, ce qui donne un int.

Essayez d'utiliser le double littéral - 157/32d, lequel est int/double, ce qui donne double.

59
Bozho

157/32 est une division d’entier car tous les littéraux numériques sont des entiers, sauf indication contraire avec un suffixe (d pour double l pendant longtemps)

la division est arrondie vers le bas (à 4) avant d'être convertie en un double (4.0) qui est ensuite arrondie vers le haut (à 4.0)

si vous utilisez une variable, vous pouvez éviter cela

double a1=157;
double a2=32;
int total = (int) Math.ceil(a1/a2);
34
ratchet freak
int total = (int) Math.ceil((double)157/32);
24
Phoebus

Dans Java, ajouter un .0 en fera un double ...

int total = (int) Math.ceil(157.0 / 32.0);
3
Scott Higgins

Lors de la division de deux nombres entiers, par exemple,

int c = (int) a / (int) b;

le résultat est un int dont la valeur est a divisée par b, arrondie à zéro. Comme le résultat est déjà arrondi, ceil() ne fait rien. Notez que cet arrondi est différent de floor(), qui arrondit à l'infini négatif. Donc, 3/2 Est égal à 1 (Et floor(1.5) est égal à 1.0, Mais (-3)/2 Est égal à -1 (Mais floor(-1.5) est égal à -2.0).

Ceci est significatif car si a/b Était toujours identique à floor(a / (double) b), vous pourriez alors implémenter ceil() de a/b Comme -( (-a) / b).

La suggestion d'obtenir ceil(a/b) de

int n = (a + b - 1) / b;, ce qui équivaut à a / b + (b - 1) / b ou (a - 1) / b + 1

fonctionne parce que ceil(a/b) est toujours supérieur à floor(a/b), sauf lorsque a/b est un nombre entier. Donc, vous voulez le remplacer par un nombre entier (ou passé), à moins que a/b Ne soit un nombre entier. Ajouter 1 - 1 / b Fera ceci. Pour les nombres entiers, cela ne les poussera pas tout à fait au prochain nombre entier. Pour tout le reste, ça ira.

Beurk. Espérons que cela a du sens. Je suis sûr qu'il existe une façon plus élégante mathématiquement de l'expliquer.

3
jorgenman
int total = (int) Math.ceil( (double)157/ (double) 32);
2
stones333

Vérifiez la solution ci-dessous pour votre question:

int total = (int) Math.ceil(157/32);

Ici, vous devriez multiplier Numerator par 1.0, il donnera alors votre réponse.

int total = (int) Math.ceil(157*1.0/32);
1
Un known

Personne n'a mentionné le plus intuitif:

int x = (int) Math.round(Math.ceil((double) 157 / 32));

Cette solution corrige l'imprécision en double division .

1
I.G. Pascual

De plus, pour convertir un nombre entier en nombre réel, vous pouvez ajouter un point:

int total = (int) Math.ceil(157/32.);

Et le résultat de (157/32.) Sera également réel. ;)

1
Vitaliy Borisok

Java fournit uniquement la division de plancher / par défaut. Mais nous pouvons écrire un plafond en termes de plancher. Voyons voir:

Tout entier y peut être écrit sous la forme y == q*k+r. Selon la définition de division de plancher (ici floor) qui arrondit r,

floor(q*k+r, k) == q  , where 0 ≤ r ≤ k-1

et de division de plafond (ici ceil) qui arrondit r₁,

ceil(q*k+r₁, k) == q+1  , where 1 ≤ r₁ ≤ k

où nous pouvons substituer r+1 pour r₁:

ceil(q*k+r+1, k) == q+1  , where 0 ≤ r ≤ k-1


Ensuite, nous substituons la première équation dans la troisième à q obtenir

ceil(q*k+r+1, k) == floor(q*k+r, k) + 1  , where 0 ≤ r ≤ k-1

Enfin, étant donné tout entier yy = q*k+r+1 pour certains q, k, r, nous avons

ceil(y, k) == floor(y-1, k) + 1

Et nous avons fini. J'espère que cela t'aides.

0
ShellayLee

Utilisez double pour lancer comme

Math.ceil((double)value) ou similaire

Math.ceil((double)value1/(double)value2);
0
Bhupinder

Il existe deux méthodes pour arrondir votre double valeur.

  1. Math.ceil
  2. Math.floor

Si vous voulez que votre réponse 4.90625 soit 4, vous devez utiliser Math.floor et si vous voulez que votre réponse 4.90625 soit 5, vous pouvez utiliser Math.ceil.

Vous pouvez vous référer au code suivant pour cela.

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);

    }

}
0
Deepak Kumbhar