2017-10-09 6 views
1

J'ai ci-dessous le morceau de code et ma précision se perd en convertissant BigDecimal en String. Toute aide à ce sujet est vraiment appréciée.
Résultat attendu: 95.10000000000000%
Résultat réel: 95.09999999999999%Java BigDecimal à la chaîne

public static String getAsString(Object value) 
{ 
    if (value == null) 
     return null; 

    if (value.toString().length() == 0) 
     return null; 

    BigDecimal inputVal = new BigDecimal(value.toString()); 

    if (inputVal == new BigDecimal(0)) 
     return ""; 

    NumberFormat numberFormat = NumberFormat.getPercentInstance(Locale.US); 
    numberFormat.setMinimumFractionDigits(14); 
    numberFormat.setMaximumFractionDigits(14); 
    if (numberFormat instanceof DecimalFormat) { 
     DecimalFormat df = (DecimalFormat) numberFormat; 
     df.setNegativePrefix("("); 
     df.setNegativeSuffix("%)"); 
    } 

    String num = null; 
    num = numberFormat.format(new BigDecimal(95.1).divide(new BigDecimal(100))); 

    return num; 
} 
+0

Quelle entrée donnez-vous à reproduire le problème? – marstran

+5

De plus, 'inputVal == new BigDecimal (0)' échouera toujours. Aucun objet ne sera jamais identique à un objet nouvellement créé. Utilisez 'equals' à la place. – marstran

+0

@marstran Alors que vous avez raison sur la mauvaise comparaison de référence, 'equals' n'est pas la bonne chose à utiliser, car' equals' pour 'BigDecimal.equals' prend en compte l'échelle (regardez les docs). Vous devriez plutôt utiliser 'BigDecimal.compareTo'. –

Répondre

0

Essayez cette

BigDecimal inputVal = new BigDecimal(value.toString()).setScale(3, RoundingMode.HALF_UP); 
+0

Il ne donne pas le résultat attendu. Vérifiez votre réponse s'il vous plaît. – imk

1

Vous pouvez utiliser setScale puis convertir en chaîne.

Je vois que vous voulez imprimer 14 chiffres, alors réglez l'échelle à 14, et utilisez arrondir.

BigDecimal inputVal = new BigDecimal(95.10000000000000).setScale(14, RoundingMode.UP); 

Ensuite, appelez toString et ajoutez le% etc.

7

Avec cette création d'instances

new BigDecimal(95.1) 

vous êtes losing some precision. Ce que vous pouvez réellement faire est d'utiliser le constructeur de chaîne:

new BigDecimal("95.1") 

Une autre façon pour votre cas est d'utiliser les méthodes d'usine:

BigDecimal.valueOf(95.1) 
BigDecimal.valueOf(100) 

interne ceux-ci utilisent la représentation de chaîne de ces chiffres pour créer un BigDecimal objet.

+0

Merci beaucoup ,, son travail maintenant –

1

Dans ce cas, en utilisant les new BigDecimal(double x) et double comme argument et il arrive que les doubles ne peuvent pas représenter x.xxxx exactement. Donc x.xxxx est "transformé" au double le plus proche possible, qui est x.0000xxxxxxxxxxxzzzzzzzzzzyyyyy et c'est ce que montre votre BigDecimal. Donc, la solution pourrait être que vous pouvez utiliser le constructeur String ou la méthode valueOf(), pour créer la représentation canonique de votre valeur double d.

En changeant votre ligne

num = numberFormat.format(new BigDecimal(95.1).divide(new BigDecimal(100))); 

à

num = numberFormat.format(BigDecimal.valueOf(95.1).divide(BigDecimal.valueOf(100))); 

ou

num = numberFormat.format(new BigDecimal("95.1").divide(new BigDecimal("100"))); 

devrait vous donner le résultat correct.

0

Vous pouvez utiliser la valeur de chaîne

num = numberFormat.format(new BigDecimal("95.1").divide(new BigDecimal("100")));