Comment obtenir des parties entières et fractionnaires à partir de doubles dans JSP / Java?


104

Comment obtenir des parties entières et fractionnaires à partir de doubles dans JSP / Java? Si la valeur est de 3,25, je veux obtenirfractional =.25 ,whole = 3

Comment pouvons-nous faire cela en Java?


4
Vous semblez avoir une idée inexacte de ce que sont la mantisse et l'exposant. Ils ne sont pas simplement «partie entière» et «partie fractionnaire». Voir en.wikipedia.org/wiki/Floating_point
Jon Skeet

En fait, j'ai lu environ 5 articles avant de dire «hé… ça ne s'appelle pas un exposant». Mon cerveau a jeté les mots et a commencé à résoudre le problème ... les mauvaises habitudes de lecture de programmes m'ont donné :)
Gishu

1
Veuillez également reformuler la question OP .. pour la postérité entre autres raisons.
Gishu

1
Cela ressemble étrangement à un problème de devoirs.
Brian Knoblauch

Oh je vois. Je me suis déjà demandé comment il obtient des résultats si étranges
Johannes Schaub - litb

Réponses:


102

http://www.java2s.com/Code/Java/Data-Type/Obtainingtheintegerandfractionalparts.htm

double num;
long iPart;
double fPart;

// Get user input
num = 2.3d;
iPart = (long) num;
fPart = num - iPart;
System.out.println("Integer part = " + iPart);
System.out.println("Fractional part = " + fPart);

Les sorties:

Integer part = 2
Fractional part = 0.2999999999999998

61
En fait, cette page est le premier résultat d'une recherche google pour "obtenir une partie fractionnaire et entière de double java" =)
Chris

12
En fait, cette réponse est incorrecte, car les valeurs supérieures à long peuvent représenter, cela donnera des nombres énormes dans la partie fractionnaire. La réponse de Dan Vinton ci-dessous est tout aussi simple et renvoie toujours le résultat correct.
arberg

2
donc en fait, ce n'est pas correct, comme vous pouvez le voir dans la sortie. l'entrée est une fraction de 3 et la sortie est 29999999 ... l'utilisation de BigDecimal au lieu de Double fera l'affaire
Alex

2
@Alex Non, l'entrée est un nombre très proche 2.3, mais sûrement pas 2.3. Et il n'y a rien de mal avec la sortie, sauf si vous voulez beaucoup plus de 10 chiffres valides. Tout ce dont vous avez besoin est un arrondi dans chaque sortie (par exemple, le format %.9f), ce qui est généralement moins pénible que BigDecimal. Le seul problème ici est le débordement.
maaartinus

1
La conversion de double en int est presque toujours une mauvaise idée. Parce que par exemple pour (long)1.0e100vous obtiendrez 0. La plupart du temps, vous avez besoin de la valeur double simplement "floored" pour laquelle il y a floor(). Si vous souhaitez utiliser à la fois des parties intégrales et fractionnaires modf(). Vraiment, c'est une mauvaise réponse.
mojuba

155
double value = 3.25;
double fractionalPart = value % 1;
double integralPart = value - fractionalPart;

12
Pourquoi ce vote est-il défavorable? Fonctionne bien, et avec ma modification fonctionnera également avec des valeurs négatives.
HRJ

La partie entière pourrait être => long longPart = (long) 3.25
jdurango

2
Ne fonctionnera pas pour neg. valeurs. Ie -3,25% 1 = 0,75 et non 0,25. Donc, intégralPart sera -3,25 - 0,75 = -4.
WindRider

2
@WindRider, j'ai vérifié le négatif .. et ses travaux .. cependant pour les décimales qui sont en petit nombre, il y aura une légère erreur. Ex. pour -03,0025, il renvoie -0,0024999999999999467 et -3,0
justshams

5
La confusion ici est due au fait que certains langages, tels que Python, %signifient modulo ( -3.25 % 1 == 0.75) et d'autres, tels que Java, Fortran, C et C ++, utilisent %pour signifier reste ( -3.25 % 1 == -0.25). WindRider l'a peut-être tapé dans une REPL Python pour des raisons de commodité, mais cette réponse est trompeuse car cette question concerne la JVM.
Jim Pivarski

24

Depuis que cette question d'un an a été soulevée par quelqu'un qui a corrigé le sujet de la question, et cette question a été identifiée jsp , et que personne ici n'a été en mesure de donner une réponse ciblée JSP, voici ma contribution ciblée sur JSP.

Utilisez JSTL (déposez simplement jstl-1.2.jar dans /WEB-INF/lib) fmt taglib. Il y a une <fmt:formatNumber>balise qui fait exactement ce que vous voulez et d'une manière assez simple avec l'aide de maxFractionDigitsetmaxIntegerDigits attributs.

Voici un SSCCE , copiez-le , collez-le et exécutez-le.

<%@ taglib uri="http://java.sun.com/jsp/jstl/fmt" prefix="fmt" %>

<%
    // Just for quick prototyping. Don't do this in real! Use servlet/javabean.
    double d = 3.25;
    request.setAttribute("d", d);
%>

<!doctype html>
<html lang="en">
    <head>
        <title>SO question 343584</title>
    </head>
    <body>
        <p>Whole: <fmt:formatNumber value="${d}" maxFractionDigits="0" />
        <p>Fraction: <fmt:formatNumber value="${d}" maxIntegerDigits="0" />
    </body>
</html>

Production:

Entier: 3

Fraction: 0,25

C'est tout. Pas besoin de le masser avec l'aide de code Java brut.


8

La question originale demandait l'exposant et la mantisse, plutôt que la partie fractionnaire et entière.

Pour obtenir l'exposant et la mantisse d'un double, vous pouvez le convertir en représentation IEEE 754 et extraire les bits comme ceci:

long bits = Double.doubleToLongBits(3.25);

boolean isNegative = (bits & 0x8000000000000000L) != 0; 
long exponent      = (bits & 0x7ff0000000000000L) >> 52;
long mantissa      =  bits & 0x000fffffffffffffL;

Le premier bit de la mantins n'est-il pas implicitement mis à 1, donc la mantisse devrait être (bits & 0x000fffffffffffffL) | 0x0010000000000000L?
agnul

Rasmus ce n'était pas une sortie ryt Sortie: exposant 0 et mantisse 2814749767106560 et si vous choisissez urs agnul, la mantisse est 0
Vinayak Bevinakatti

Cassé avec 4 votes positifs :) Bien que je vois ce que le code essaie de faire en supprimant la double valeur à ses articulations, le code ne semble pas afficher les bonnes valeurs.
Gishu

@agnul: Je pense que "mantisse" se réfère généralement à la valeur des bits. Vous pouvez simplement le convertir en significand en ajoutant (parfois) un bit au début. Mais selon Wikipedia, le mot mantisse est désormais obsolète au profit de «fraction».
Rasmus Faber

5

Logique principale, vous devez d'abord trouver le nombre de chiffres après la virgule décimale.
Ce code fonctionne pour n'importe quel nombre jusqu'à 16 chiffres. Si vous utilisez BigDecimal, vous pouvez l'exécuter uniquement pour jusqu'à 18 chiffres. mettez la valeur d'entrée (votre nombre) à la variable "num", ici à titre d'exemple je l'ai codée en dur.

double num, temp=0;
double frac,j=1;

num=1034.235;
// FOR THE FRACTION PART
do{
j=j*10;
temp= num*j;
}while((temp%10)!=0);       

j=j/10;
temp=(int)num;
frac=(num*j)-(temp*j);

System.out.println("Double number= "+num);      
System.out.println("Whole part= "+(int)num+" fraction part= "+(int)frac);

Mec, c'est une réponse extrêmement compliquée à un problème simple. Avez-vous jeté un œil à la réponse acceptée?
Gris

1
Maintenant, la personne qui a voté contre (pas moi d'ailleurs) aurait dû expliquer pourquoi il y avait eu un vote contre. Ce n'est pas bon. Mais nous avons tous eu un score de 1 à un moment ou à un autre.
Gris

2
@Gray, la question était de séparer 3,25 par '3' et '25', et la réponse acceptée ne donnera jamais '25', elle donnera toujours '2599999999'
OnePunchMan

@Gray Je sais qui a voté contre, c'était un gars nommé Eji (ancien utilisateur) se moquant de chacun de mes commentaires, réponses et questions que je publie dans ce blog. Enfin, je me plains au modérateur.
OnePunchMan

2
Cette réponse est très utile si vous voulez la partie fractionnaire sous forme d'entier
Guilherme Campos Hazan

5

La mantisse et l'exposant d'un nombre à virgule flottante double IEEE sont les valeurs telles que

value = sign * (1 + mantissa) * pow(2, exponent)

si la mantisse est de la forme 0.101010101_base 2 (c'est-à-dire que son bit le plus significatif est décalé pour être après le point binaire) et que l'exposant est ajusté pour la polarisation.

Depuis 1.6, java.lang.Math fournit également une méthode directe pour obtenir l'exposant non biaisé (appelé getExponent (double))

Cependant, les nombres que vous demandez sont les parties intégrales et fractionnaires du nombre, qui peuvent être obtenues en utilisant

integral = Math.floor(x)
fractional = x - Math.floor(x)

bien que vous souhaitiez peut-être traiter les nombres négatifs différemment (floor(-3.5) == -4.0) , selon la raison pour laquelle vous voulez les deux parties.

Je vous suggère fortement de ne pas appeler ces mantisses et exposants.


4

Je ne sais pas si c'est plus rapide mais j'utilise

float fp = ip % 1.0f;

3

[Modifier: La question demandait à l'origine comment obtenir la mantisse et l'exposant.]

n est le nombre pour obtenir la vraie mantisse / exposant:

exponent = int(log(n))
mantissa = n / 10^exponent

Ou, pour obtenir la réponse que vous recherchiez:

exponent = int(n)
mantissa = n - exponent

Ce ne sont pas exactement Java, mais devraient être faciles à convertir.


3

La partie entière est obtenue à partir de la conversion simple et pour le fractionnement de chaîne fractionnaire:

double value = 123.004567890

int integerPart = (int) value; // 123

int fractionPart = 
  Integer.valueOf(String.valueOf(value)
      .split(".")[1]); // 004567890

/**
* To control zeroes omitted from start after parsing.
*/
int decimals =
  String.valueOf(value)
      .split(".")[1].length(); // 9

1

Et si votre numéro est 2,39999999999999. Je suppose que vous voulez obtenir la valeur décimale exacte. Ensuite, utilisez BigDecimal:

Integer x,y,intPart;
BigDecimal bd,bdInt,bdDec;
bd = new BigDecimal("2.39999999999999");
intPart = bd.intValue();
bdInt = new BigDecimal(intPart);
bdDec = bd.subtract(bdInt);
System.out.println("Number : " + bd);
System.out.println("Whole number part : " + bdInt);
System.out.println("Decimal number part : " + bdDec);

0

Étant donné que la fmt:formatNumberbalise ne donne pas toujours le résultat correct, voici une autre approche uniquement JSP: elle formate simplement le nombre sous forme de chaîne et effectue le reste du calcul sur la chaîne, car cela est plus facile et n'implique pas davantage de virgule flottante arithmétique.

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>

<%
  double[] numbers = { 0.0, 3.25, 3.75, 3.5, 2.5, -1.5, -2.5 };
  pageContext.setAttribute("numbers", numbers);
%>

<html>
  <body>
    <ul>
      <c:forEach var="n" items="${numbers}">
        <li>${n} = ${fn:substringBefore(n, ".")} + ${n - fn:substringBefore(n, ".")}</li>
      </c:forEach>
    </ul>
  </body>
</html>

Essayez simplement tous les chiffres de mon exemple. fmt:formatNumberarrondit son argument, ce qui n'est pas voulu dans ce cas.
Roland Illig

0

Beaucoup de ces réponses comportent d'horribles erreurs d'arrondi, car elles transposent des nombres d'un type à un autre. Que diriez-vous:

double x=123.456;
double fractionalPart = x-Math.floor(x);
double wholePart = Math.floor(x);

@justshams Et l'utilisation Math.abs?
Stephan

0

La réponse acceptée ne fonctionne pas bien pour les nombres négatifs entre -0 et -1.0 Donnez également la partie fractionnaire négative.

Par exemple: pour le numéro -0,35

Retour

Partie entière = 0 Partie fractionnaire = -0,35

Si vous travaillez avec des coordonnées GPS, il est préférable d'avoir un résultat avec le signe sur la partie entière comme:

Partie entière = -0 Partie fractionnaire = 0,35

Ces nombres sont utilisés par exemple pour les coordonnées GPS, où sont importants le signe pour la position Lat ou Long

Proposer un code:

    double num;
    double iPart;
    double fPart;

    // Get user input
    num = -0.35d;
    iPart = (long) num;
    //Correct numbers between -0.0 and -1.0
    iPart = (num<=-0.0000001 && num>-1.0)? -iPart : iPart ;
    fPart = Math.abs(num - iPart);
    System.out.println(String.format("Integer part = %01.0f",iPart));
    System.out.println(String.format("Fractional part = %01.04f",fPart));

Production:

Integer part = -0
Fractional part = 0,3500

0

Depuis Java 8, vous pouvez utiliser Math.floorDiv .

Il renvoie le plus grand (le plus proche de l'infini positif) int inférieure ou égale au quotient algébrique.

Quelques exemples:

floorDiv(4, 3) == 1
floorDiv(-4, 3) == -2

Alternativement, l' /opérateur peut être utilisé:

(4 / 3) == 1
(-4 / 3) == -1

Références:


0

J'utiliserais BigDecimal pour la solution. Comme ça:

    double value = 3.25;
    BigDecimal wholeValue = BigDecimal.valueOf(value).setScale(0, BigDecimal.ROUND_DOWN);
    double fractionalValue = value - wholeValue.doubleValue();

0
String value = "3.06";

if(!value.isEmpty()){
    if(value.contains(".")){    
        String block = value.substring(0,value.indexOf("."));
        System.out.println(block);
    }else{
        System.out.println(value);
    }
}

Cette réponse a été signalée comme étant de mauvaise qualité. S'il répond à la question, pensez à ajouter un peu de texte pour expliquer son fonctionnement.
lmo le

0
// target float point number
double d = 3.025;

// transfer the number to string
DecimalFormat df = new DecimalFormat();
df.setDecimalSeparatorAlwaysShown(false);
String format = df.format(d);

// split the number into two fragments
int dotIndex = format.indexOf(".");
int iPart = Integer.parseInt(format.substring(0, dotIndex)); // output: 3
double fPart = Double.parseDouble(format.substring(dotIndex)); // output: 0.025

0

OK, c'est peut-être tard, mais je pense que la meilleure approche et la plus précise consiste à utiliser BigDecimal

double d = 11.38;

BigDecimal bigD = BigDecimal.valueOf(d);
int intPart = bigD.intValue();
double fractionalPart = bigD.subtract(BigDecimal.valueOf(intPart)).doubleValue();

System.out.println(intPart); // 11
System.out.println(fractionalPart ); //0.38

Si vous avez un double, il a une imprécision de flotteur. Le convertir en BigDecimal ne restaure pas comme par magie sa précision.
Taschi

@Taschi je pense que la question est de séparer l'int et la partie fractionnaire, pas de restaurer sa précision!
Omar Elashry le

Omar, vous avez spécifiquement dit que votre approche était «plus précise», ce qui, à mon avis, n'est tout simplement pas vrai. Votre réponse est tout à fait acceptable, mais cette formulation me semble trompeuse, c'est pourquoi je l'ai commentée.
Taschi

@Taschi, j'ai dit cela parce que dans de nombreuses réponses, vous perdez de la valeur lorsque vous obtenez la sortie, par exemple input (5.03) output int = 5 , fractional = 0.0299999, nous parlons d'entrées et de sorties, vous mettez de la valeur et récupérez votre valeur sans en perdre 0,001%! et ce précis, pas trompeur!
Omar Elashry

Oui. Vous perdez de la précision lorsque vous stockez quelque chose comme un double en premier lieu. L'arrondi lors de la conversion en BigDecimal perd également de la précision. Ces deux pertes de précision peuvent s'annuler, mais cela ne "restaure" pas la précision, car la restauration de la précision est mathématiquement impossible. Vous ne pouvez pas extraire des informations de rien.
Taschi

-2
public class MyMain2 {
    public static void main(String[] args) {
        double myDub;
        myDub=1234.5678;
        long myLong;
        myLong=(int)myDub;
        myDub=(myDub%1)*10000;
        int myInt=(int)myDub;
        System.out.println(myLong + "\n" + myInt);
    }
}

Cela ne fonctionne que si le nombre a exactement 4 décimales. Pas autrement.
Marquis of Lorne
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.