2009-03-23 5 views

Répondre

2

Je suis sûr qu'il y a un moyen plus élégant, mais voyez si cela fonctionne?

import static org.junit.Assert.assertEquals; 

import java.text.ChoiceFormat; 
import java.text.DecimalFormat; 
import java.text.FieldPosition; 
import java.text.NumberFormat; 
import java.text.ParsePosition; 

import org.junit.Test; 

public class NumberFormatTest { 
    @Test 
    public void testNumberFormat() { 
     NumberFormat nf = new MyNumberFormat(); 
     assertEquals("-1234.4", nf.format(-1234.4)); 
     assertEquals("0.0", nf.format(0)); 
     assertEquals("+0.3", nf.format(0.3)); 
     assertEquals("+12.0", nf.format(12)); 
    } 
} 

class MyNumberFormat extends NumberFormat { 

    private DecimalFormat df = new DecimalFormat("0.0#"); 
    private ChoiceFormat cf = new ChoiceFormat(new double[] { 0.0, 
      ChoiceFormat.nextDouble(0.0) }, new String[] { "", "+" }); 

    @Override 
    public StringBuffer format(double number, StringBuffer toAppendTo, 
      FieldPosition pos) { 
     return toAppendTo.append(cf.format(number)).append(df.format(number)); 
    } 

    @Override 
    public StringBuffer format(long number, StringBuffer toAppendTo, 
      FieldPosition pos) { 
     return toAppendTo.append(cf.format(number)).append(df.format(number)); 
    } 

    @Override 
    public Number parse(String source, ParsePosition parsePosition) { 
     throw new UnsupportedOperationException(); 
    } 
} 

Selon DecimalFormat

Le sous-motif négatif est facultative; en cas d'absence, le sous-motif positif préfixé par le signe moins localisé (« - » dans la plupart des lieux) est utilisé comme sous-modèle négatif

Par conséquent new DecimalFormat("0.0#") est équivalent à new DecimalFormat("0.0#;-0.0#")

Alors cela nous donnerait: -1234.5 et 1234.5

maintenant, pour ajouter le '+' aux numéros positve, j'utilise un ChoiceFormat

  • 0.0 <= X < ChoiceFormat.nextDouble(0.0) utilisera un format de choix de "". ChoiceFormat.nextDouble(0.0) est le plus petit nombre supérieur à 0.0.
  • ChoiceFormat.nextDouble(0.0) <= X < 1 utilisera un format de choix de "+".

S'il n'y a pas de correspondance, alors soit le premier ou le dernier indice est utilisé, selon que le nombre (X) est trop faible ou trop élevée. Si le tableau de limite n'est pas dans l'ordre croissant, les résultats du formatage seront incorrects. ChoiceFormat accepte également \ u221E comme équivalent à l'infini (INF).

Par conséquent

  • Double.NEGATIVE_INFINITY <= X < 0 utilisera "".
  • 1 <= X < Double.POSITIVE_INFINITY utilisera "+".
+0

Est-ce un long chemin, rond-point de dire que ChoiceFormat est ce qu'il cherche? –

0

Java a à la fois un "zéro négatif" et un "zéro positif". Ils ont des représentations différentes, mais comparent comme étant égaux les uns aux autres.

Si vous devez avoir un signe plus précédant vos valeurs positives, mais vous ne voulez pas pour zéro positif, alors vous devrez peut-être faire quelque chose comme ceci pour effacer temporairement le préfixe:

try { 
    if (val == 0.0) { 
     format.setPositivePrefix(""); 
    } 
    result = format.format(val); 
} 
finally { 
    format.setPositivePrefix("+"); 
} 
1

Merci beaucoup de gars, de très bonnes idées ici. En fonction de ce qui a été suggéré, j'ai décidé d'utiliser deux formats: zeroFormat pour le boîtier spécial pour 0.0d, et nonZeroFormat pour le reste des cas. Je cache l'implémentation derrière un IDisplayableValueFormatter (qui est utilisé par un contrôle d'interface utilisateur personnalisé) et n'a pas besoin d'adhérer au contrat/interface NumberFormat.

0

Je viens de croiser ce sur un projet, et je ne ai trouvé aucun des réponses ici particulièrement satisfaisante.

Ce que j'ai pu faire au lieu (qui peut ou peut ne pas fonctionner pour vous):

// Convert negative zero to positive zero. Even though this 
// looks like it should be a no-op, it isn't. 
double correctedValue = (value == 0.0 ? 0.0 : value); 

Ensuite, la valeur sera correctement mis en forme par la classe DecimalFormat.

Je suis en fait un peu surpris que Java ne dispose pas d'une construction similaire intégrée.