web-dev-qa-db-fra.com

Quelle est la meilleure pratique pour arrondir un nombre à 2 décimales?

J'utilise Eclipse + Android SDK.

Je dois arrondir une valeur flottante à 2 décimales. J'utilise habituellement le prochain "truc" en utilisant la bibliothèque Math.

float accelerometerX = accelerometerX * 100;
    accelerometerX = round(accelerometerX);
    Log.d("Test","" + accelerometerX/100);

Mais j'estime que ce n'est pas la meilleure façon de le faire.

Existe-t-il une bibliothèque pour effectuer ce type d'opérations?

Merci d'avance.

100
vgonisanz

Je travaillais avec des statistiques dans Java il y a 2 ans et j'ai toujours les codes d'une fonction qui vous permet d'arrondir un nombre au nombre de décimales que vous voulez. Maintenant, vous avez besoin de deux, mais vous voudrez peut-être essayer avec 3 de comparer les résultats, et cette fonction vous donne cette liberté.

/**
* Round to certain number of decimals
* 
* @param d
* @param decimalPlace
* @return
*/
public static float round(float d, int decimalPlace) {
    BigDecimal bd = new BigDecimal(Float.toString(d));
    bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP);
    return bd.floatValue();
}

Vous devez décider si vous voulez arrondir ou décroître. Dans mon exemple de code, j'arrondis.

J'espère que ça aide.

EDIT

Si vous voulez conserver le nombre de décimales quand elles sont égales à zéro (je suppose que c'est juste pour les afficher à l'utilisateur), il vous suffit de changer le type de fonction de float à BigDecimal, comme ceci:

public static BigDecimal round(float d, int decimalPlace) {
    BigDecimal bd = new BigDecimal(Float.toString(d));
    bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP);       
    return bd;
}

Et appelez ensuite la fonction de cette façon:

float x = 2.3f;
BigDecimal result;
result=round(x,2);
System.out.println(result);

Cela va imprimer:

2.30
147
Jav_Rock

Testons 3 méthodes:
1)

public static double round1(double value, int scale) {
    return Math.round(value * Math.pow(10, scale)) / Math.pow(10, scale);
}

2)

public static float round2(float number, int scale) {
    int pow = 10;
    for (int i = 1; i < scale; i++)
        pow *= 10;
    float tmp = number * pow;
    return ( (float) ( (int) ((tmp - (int) tmp) >= 0.5f ? tmp + 1 : tmp) ) ) / pow;
}

3)

public static float round3(float d, int decimalPlace) {
    return BigDecimal.valueOf(d).setScale(decimalPlace, BigDecimal.ROUND_HALF_UP).floatValue();
}



Nombre est 0.23453f
Nous allons tester 100 000 itérations par méthode.

Résultats:
Temps 1 - 18 ms
Temps 2 - 1 ms
Temps 3 - 378 ms


Testé sur un ordinateur portable
Intel i3-3310M CPU 2.4GHz

46
Ivan Stin
double roundTwoDecimals(double d) {
  DecimalFormat twoDForm = new DecimalFormat("#.##");
  return Double.valueOf(twoDForm.format(d));
}
33
Shadow

Voici une implémentation plus courte comparée à @ Jav_Rock

   /**
     * Round to certain number of decimals
     * 
     * @param d
     * @param decimalPlace the numbers of decimals
     * @return
     */

    public static float round(float d, int decimalPlace) {
         return BigDecimal.valueOf(d).setScale(decimalPlace,BigDecimal.ROUND_HALF_UP).floatValue();
    }



    System.out.println(round(2.345f,2));//two decimal digits, //2.35
14
Jaskey

J'ai essayé de supporter les valeurs -ve de l'excellente 2e méthode de @Ivan Stin. (Le gros crédit revient à @Ivan Stin pour sa méthode)

public static float round(float value, int scale) {
    int pow = 10;
    for (int i = 1; i < scale; i++) {
        pow *= 10;
    }
    float tmp = value * pow;
    float tmpSub = tmp - (int) tmp;

    return ( (float) ( (int) (
            value >= 0
            ? (tmpSub >= 0.5f ? tmp + 1 : tmp)
            : (tmpSub >= -0.5f ? tmp : tmp - 1)
            ) ) ) / pow;

    // Below will only handles +ve values
    // return ( (float) ( (int) ((tmp - (int) tmp) >= 0.5f ? tmp + 1 : tmp) ) ) / pow;
}

Vous trouverez ci-dessous les cas de tests que j'ai essayés. S'il vous plaît laissez-moi savoir si cela ne concerne pas d'autres cas.

@Test
public void testFloatRound() {
    // +ve values
    Assert.assertEquals(0F, NumberUtils.round(0F), 0);
    Assert.assertEquals(1F, NumberUtils.round(1F), 0);
    Assert.assertEquals(23.46F, NumberUtils.round(23.4567F), 0);
    Assert.assertEquals(23.45F, NumberUtils.round(23.4547F), 0D);
    Assert.assertEquals(1.00F, NumberUtils.round(0.49999999999999994F + 0.5F), 0);
    Assert.assertEquals(123.12F, NumberUtils.round(123.123F), 0);
    Assert.assertEquals(0.12F, NumberUtils.round(0.123F), 0);
    Assert.assertEquals(0.55F, NumberUtils.round(0.55F), 0);
    Assert.assertEquals(0.55F, NumberUtils.round(0.554F), 0);
    Assert.assertEquals(0.56F, NumberUtils.round(0.556F), 0);
    Assert.assertEquals(123.13F, NumberUtils.round(123.126F), 0);
    Assert.assertEquals(123.15F, NumberUtils.round(123.15F), 0);
    Assert.assertEquals(123.17F, NumberUtils.round(123.1666F), 0);
    Assert.assertEquals(123.46F, NumberUtils.round(123.4567F), 0);
    Assert.assertEquals(123.87F, NumberUtils.round(123.8711F), 0);
    Assert.assertEquals(123.15F, NumberUtils.round(123.15123F), 0);
    Assert.assertEquals(123.89F, NumberUtils.round(123.8909F), 0);
    Assert.assertEquals(124.00F, NumberUtils.round(123.9999F), 0);
    Assert.assertEquals(123.70F, NumberUtils.round(123.7F), 0);
    Assert.assertEquals(123.56F, NumberUtils.round(123.555F), 0);
    Assert.assertEquals(123.00F, NumberUtils.round(123.00F), 0);
    Assert.assertEquals(123.50F, NumberUtils.round(123.50F), 0);
    Assert.assertEquals(123.93F, NumberUtils.round(123.93F), 0);
    Assert.assertEquals(123.93F, NumberUtils.round(123.9312F), 0);
    Assert.assertEquals(123.94F, NumberUtils.round(123.9351F), 0);
    Assert.assertEquals(123.94F, NumberUtils.round(123.9350F), 0);
    Assert.assertEquals(123.94F, NumberUtils.round(123.93501F), 0);
    Assert.assertEquals(99.99F, NumberUtils.round(99.99F), 0);
    Assert.assertEquals(100.00F, NumberUtils.round(99.999F), 0);
    Assert.assertEquals(100.00F, NumberUtils.round(99.9999F), 0);

    // -ve values
    Assert.assertEquals(-123.94F, NumberUtils.round(-123.93501F), 0);
    Assert.assertEquals(-123.00F, NumberUtils.round(-123.001F), 0);
    Assert.assertEquals(-0.94F, NumberUtils.round(-0.93501F), 0);
    Assert.assertEquals(-1F, NumberUtils.round(-1F), 0);
    Assert.assertEquals(-0.50F, NumberUtils.round(-0.50F), 0);
    Assert.assertEquals(-0.55F, NumberUtils.round(-0.55F), 0);
    Assert.assertEquals(-0.55F, NumberUtils.round(-0.554F), 0);
    Assert.assertEquals(-0.56F, NumberUtils.round(-0.556F), 0);
    Assert.assertEquals(-0.12F, NumberUtils.round(-0.1234F), 0);
    Assert.assertEquals(-0.12F, NumberUtils.round(-0.123456789F), 0);
    Assert.assertEquals(-0.13F, NumberUtils.round(-0.129F), 0);
    Assert.assertEquals(-99.99F, NumberUtils.round(-99.99F), 0);
    Assert.assertEquals(-100.00F, NumberUtils.round(-99.999F), 0);
    Assert.assertEquals(-100.00F, NumberUtils.round(-99.9999F), 0);
}
6
manikanta

Voici une solution simple en une ligne

((int) ((value + 0.005f) * 100)) / 100f
1
Ilya Bystrov