Een getal afronden op n decimalen in Java

Wat ik zou willen is een methode om een double om te zetten in een string die wordt afgerond met behulp van de half-up methode – d.w.z. als het decimaalteken dat moet worden afgerond 5 is, wordt altijd naar boven afgerond naar het volgende getal. Dit is de standaardmethode voor het afronden die de meeste mensen in de meeste situaties verwachten.

Ik wil ook dat alleen significante cijfers worden weergegeven, d.w.z. er mogen geen nullen achter staan.

Ik weet dat een methode om dit te doen is om de String.formatmethode te gebruiken:

String.format("%.5g%n", 0.912385);

retourneert:

0.91239

wat geweldig is, maar het geeft altijd getallen weer met 5 decimalen, zelfs als ze niet significant zijn:

String.format("%.5g%n", 0.912300);

retourneert:

0.91230

Een andere methode is om de DecimalFormatterte gebruiken:

DecimalFormat df = new DecimalFormat("#.#####");
df.format(0.912385);

retourneert:

0.91238

Maar zoals je kunt zien, wordt hier half-even afronding gebruikt. Dat wil zeggen dat het naar beneden wordt afgerond als het vorige cijfer even is. Wat ik zou willen is dit:

0.912385 -> 0.91239
0.912300 -> 0.9123

Wat is de beste manier om dit in Java te bereiken?


Antwoord 1, autoriteit 100%

Gebruik setRoundingMode, stel de RoundingModeExpliciet om uw probleem met de halve ronde af te handelen, gebruik vervolgens het formaatpatroon voor uw vereiste uitvoer.

Voorbeeld:

DecimalFormat df = new DecimalFormat("#.####");
df.setRoundingMode(RoundingMode.CEILING);
for (Number n : Arrays.asList(12, 123.12345, 0.23, 0.1, 2341234.212431324)) {
    Double d = n.doubleValue();
    System.out.println(df.format(d));
}

geeft de uitvoer:

12
123.1235
0.23
0.1
2341234.2125

bewerken : het oorspronkelijke antwoord geeft geen betrekking op de nauwkeurigheid van de dubbele waarden. Dat is goed als het je niet om geeft, of het nu om of naar beneden gaat. Maar als u een nauwkeurige afronding wilt, moet u rekening houden met de verwachte juistheid van de waarden. Drijvende puntenwaarden hebben intern een binaire weergave. Dat betekent dat een waarde zoals 2.7735 niet daadwerkelijk die exacte waarde intern is. Het kan iets groter of iets kleiner zijn. Als de interne waarde iets kleiner is, dan zal het niet ronden tot 2.7740. Om die situatie te verhelpen, moet u zich bewust zijn van de nauwkeurigheid van de waarden waarmee u werkt, en die waarde toevoegen of aftrekken voordat u aftelt. Wanneer u bijvoorbeeld weet dat uw waarden nauwkeurig zijn tot 6 cijfers, voeg dan naar ronde halft-way-waarden op, deze nauwkeurigheid toe aan de waarde:

Double d = n.doubleValue() + 1e-6;

Als u naar beneden wilt afronden, trekt u de nauwkeurigheid af.


Antwoord 2, autoriteit 60%

Ervan uitgaande dat valueeen doubleis, kunt u het volgende doen:

(double)Math.round(value * 100000d) / 100000d

Dat is voor een nauwkeurigheid van 5 cijfers. Het aantal nullen geeft het aantal decimalen aan.


Antwoord 3, autoriteit 25%

new BigDecimal(String.valueOf(double)).setScale(yourScale, BigDecimal.ROUND_HALF_UP);

u krijgt een BigDecimal. Om de string eruit te halen, roep je de BigDecimal‘s toStringmethode aan, of de toPlainStringmethode voor Java 5+ voor een gewoon formaat snaar.

Voorbeeldprogramma:

package trials;
import java.math.BigDecimal;
public class Trials {
    public static void main(String[] args) {
        int yourScale = 10;
        System.out.println(BigDecimal.valueOf(0.42344534534553453453-0.42324534524553453453).setScale(yourScale, BigDecimal.ROUND_HALF_UP));
    }

Antwoord 4, autoriteit 15%

U kunt ook de

. gebruiken

DecimalFormat df = new DecimalFormat("#.00000");
df.format(0.912385);

om er zeker van te zijn dat u de laatste nullen heeft.


Antwoord 5, autoriteit 11%

Zoals anderen al hebben opgemerkt, is het juiste antwoord het gebruik van DecimalFormatof BigDecimal. Drijvende komma heeft geen decimalen, dus je kunt in de eerste plaats onmogelijk afronden/afkappen op een specifiek aantal. Je moet in een decimale radix werken, en dat is wat die twee klassen doen.

Ik plaats de volgende code als een counter-voorbeeld naar alle antwoorden in deze thread en inderdaad inderdaad over de stackoverflow (en elders) die vermenigvuldiging aanbevelen, gevolgd door truncatie gevolgd door divisie. Het is gevestigd op pleitbezorgingen van deze techniek om uit te leggen waarom de volgende code de verkeerde uitvoer in meer dan 92% van de gevallen produceert.

public class RoundingCounterExample
{
    static float roundOff(float x, int position)
    {
        float a = x;
        double temp = Math.pow(10.0, position);
        a *= temp;
        a = Math.round(a);
        return (a / (float)temp);
    }
    public static void main(String[] args)
    {
        float a = roundOff(0.0009434f,3);
        System.out.println("a="+a+" (a % .001)="+(a % 0.001));
        int count = 0, errors = 0;
        for (double x = 0.0; x < 1; x += 0.0001)
        {
            count++;
            double d = x;
            int scale = 2;
            double factor = Math.pow(10, scale);
            d = Math.round(d * factor) / factor;
            if ((d % 0.01) != 0.0)
            {
                System.out.println(d + " " + (d % 0.01));
                errors++;
            }
        }
        System.out.println(count + " trials " + errors + " errors");
    }
}

Uitvoer van dit programma:

10001 trials 9251 errors

EDIT: Om enkele opmerkingen hieronder te pakken, maak ik het modulusgedeelte van de testlus opnieuw aan met BigDecimalen new MathContext(16)voor de Modulus bediening als volgt:

public static void main(String[] args)
{
    int count = 0, errors = 0;
    int scale = 2;
    double factor = Math.pow(10, scale);
    MathContext mc = new MathContext(16, RoundingMode.DOWN);
    for (double x = 0.0; x < 1; x += 0.0001)
    {
        count++;
        double d = x;
        d = Math.round(d * factor) / factor;
        BigDecimal bd = new BigDecimal(d, mc);
        bd = bd.remainder(new BigDecimal("0.01"), mc);
        if (bd.multiply(BigDecimal.valueOf(100)).remainder(BigDecimal.ONE, mc).compareTo(BigDecimal.ZERO) != 0)
        {
            System.out.println(d + " " + bd);
            errors++;
        }
    }
    System.out.println(count + " trials " + errors + " errors");
}

Resultaat:

10001 trials 4401 errors

6, Autoriteit 11%

Stel dat u

hebt

double d = 9232.129394d;

u kunt BigDecimal

BigDecimal bd = new BigDecimal(d).setScale(2, RoundingMode.HALF_EVEN);
d = bd.doubleValue();

of zonder bigdecimaal

d = Math.round(d*100)/100.0d;

Met beide oplossingen d == 9232.13


7, Autoriteit 8%

U kunt de klasse Decimalformat gebruiken.

double d = 3.76628729;
DecimalFormat newFormat = new DecimalFormat("#.##");
double twoDecimal =  Double.valueOf(newFormat.format(d));

8, Autoriteit 5%

Real’s Java How-to postsdeze oplossing, die ook compatibel is voor versies vóór Java 1.6.

BigDecimal bd = new BigDecimal(Double.toString(d));
bd = bd.setScale(decimalPlace, BigDecimal.ROUND_HALF_UP);
return bd.doubleValue();

UPDATE: BigDecimal.ROUND_HALF_UP is verouderd – gebruik RoundingMode

BigDecimal bd = new BigDecimal(Double.toString(number));
bd = bd.setScale(decimalPlaces, RoundingMode.HALF_UP);
return bd.doubleValue();

Antwoord 9, autoriteit 4%

double myNum = .912385;
int precision = 10000; //keep 4 digits
myNum= Math.floor(myNum * precision +.5)/precision;

Antwoord 10, autoriteit 4%

@Milhous: het decimale formaat voor afronding is uitstekend:

U kunt ook de

. gebruiken

DecimalFormat df = new DecimalFormat("#.00000");
df.format(0.912385);

om er zeker van te zijn dat u de laatste nullen heeft.

Ik zou hieraan willen toevoegen dat deze methode erg goed is in het leveren van een echte
numeriek, afrondingsmechanisme – niet alleen visueel, maar ook bij verwerking.

Hypothetisch: u moet een afrondingsmechanisme in een GUI implementeren
programma. Om de nauwkeurigheid/precisie van een resultaatuitvoer eenvoudig te wijzigen
verander het caret-formaat (d.w.z. tussen de haakjes). Dus dat:

DecimalFormat df = new DecimalFormat("#0.######");
df.format(0.912385);

zou als uitvoer terugkeren: 0.912385

DecimalFormat df = new DecimalFormat("#0.#####");
df.format(0.912385);

zou terugkeren als uitvoer: 0.91239

DecimalFormat df = new DecimalFormat("#0.####");
df.format(0.912385);

zou terugkeren als uitvoer: 0.9124

[EDIT: Ook als het Caret-formaat is zoals SO (“# 0. ############”) en u
Voer een decimaal in, b.v. 3.1415926, voor het belang van de argument, decimalformat
produceert geen vuilnis (bijvoorbeeld achtervolging nullen) en zal terugkeren:
3.1415926.. Als u op die manier hellend bent. Toegegeven, het is een beetje uitgebreid
Want het leuk vinden van wat Dev’s – maar hey, het heeft een footprint met een laag geheugen
Tijdens de verwerking en is zeer eenvoudig te implementeren.]

Dus in wezen, de schoonheid van decimalformat is dat het tegelijkertijd de string behandelt
uiterlijk – evenals het niveau van afrondingsprecisie. Ergo: jij
Krijg twee voordelen voor de prijs van een code-implementatie. 😉


11, Autoriteit 2%

Hier is een samenvatting van wat u kunt gebruiken als u het resultaat wilt als tekenreeks:

  1. decimalformat # setRoundingmode () :

    DecimalFormat df = new DecimalFormat("#.#####");
    df.setRoundingMode(RoundingMode.HALF_UP);
    String str1 = df.format(0.912385)); // 0.91239
    
  2. bigdecimal # setscale ()

    String str2 = new BigDecimal(0.912385)
        .setScale(5, BigDecimal.ROUND_HALF_UP)
        .toString();
    

Hier is een suggestie van welke bibliotheken je kunt gebruiken als je als resultaat doublewilt. Ik zou het echter niet aanbevelen voor stringconversie, omdat double mogelijk niet precies kan weergeven wat je wilt (zie bijvoorbeeld hier):

  1. Precisievan Apache Commons Math

    double rounded = Precision.round(0.912385, 5, BigDecimal.ROUND_HALF_UP);
    
  2. Functiesvan Colt

    double rounded = Functions.round(0.00001).apply(0.912385)
    
  3. Hulpprogramma’svan Weka

    double rounded = Utils.roundDouble(0.912385, 5)
    

Antwoord 12, autoriteit 2%

U kunt de volgende hulpprogrammamethode gebruiken-

public static double round(double valueToRound, int numberOfDecimalPlaces)
{
    double multipicationFactor = Math.pow(10, numberOfDecimalPlaces);
    double interestedInZeroDPs = valueToRound * multipicationFactor;
    return Math.round(interestedInZeroDPs) / multipicationFactor;
}

Antwoord 13, autoriteit 2%

Een beknopte oplossing:

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

Zie ook, https://stackoverflow.com/a/22186845/212950
Met dank aan jpdymondvoor het aanbieden hiervan.


Antwoord 14

U kunt BigDecimal gebruiken

BigDecimal value = new BigDecimal("2.3");
value = value.setScale(0, RoundingMode.UP);
BigDecimal value1 = new BigDecimal("-2.3");
value1 = value1.setScale(0, RoundingMode.UP);
System.out.println(value + "n" + value1);

Zie: http://www.javabeat.net/precise- afronding-van-decimalen-using-rounding-mode-enumeration/


Antwoord 15

Als je echt decimale getallen wilt voor berekening (en niet alleen voor uitvoer), gebruik dan geen binair gebaseerde drijvende-komma-indeling zoals dubbel.

Use BigDecimal or any other decimal-based format.

Ik gebruik BigDecimal voor berekeningen, maar houd er rekening mee dat dit afhankelijk is van de grootte van
nummers waar je mee te maken hebt. In de meeste van mijn implementaties vind ik parsing van dubbele of
geheel getal tot Lang is voldoende voor berekeningen met zeer grote getallen.

In feite heb ik
onlangs gebruikt parsed-to-long om nauwkeurige representaties te krijgen (in tegenstelling tot hex-resultaten)
in een GUI voor getallen zo groot als ################################# tekens (als een
voorbeeld).


16

Sinds ik geen volledig antwoord op dit thema vond, heb ik een klasse samengesteld die dit goed zou moeten aangaan, met ondersteuning voor:

  • Formatteren : eenvoudig een dubbele opserie formatteren met een bepaald aantal decimalen
  • Parsing : Ontleed de geformatteerde waarde terug naar het dubbele
  • Locale : formaat en parse met behulp van de standaardlocale
  • Exponential Notation : Begin met het gebruik van exponentiële notatie na een bepaalde drempelwaarde

Gebruik is vrij eenvoudig :

(in het belang van dit voorbeeld gebruik ik een aangepaste locale)

public static final int DECIMAL_PLACES = 2;
NumberFormatter formatter = new NumberFormatter(DECIMAL_PLACES);
String value = formatter.format(9.319); // "9,32"
String value2 = formatter.format(0.0000005); // "5,00E-7"
String value3 = formatter.format(1324134123); // "1,32E9"
double parsedValue1 = formatter.parse("0,4E-2", 0); // 0.004
double parsedValue2 = formatter.parse("0,002", 0); // 0.002
double parsedValue3 = formatter.parse("3423,12345", 0); // 3423.12345

Hier is de les:

import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.ParseException;
import java.util.Locale;
public class NumberFormatter {
    private static final String SYMBOL_INFINITE           = "\u221e";
    private static final char   SYMBOL_MINUS              = '-';
    private static final char   SYMBOL_ZERO               = '0';
    private static final int    DECIMAL_LEADING_GROUPS    = 10;
    private static final int    EXPONENTIAL_INT_THRESHOLD = 1000000000; // After this value switch to exponential notation
    private static final double EXPONENTIAL_DEC_THRESHOLD = 0.0001; // Below this value switch to exponential notation
    private DecimalFormat decimalFormat;
    private DecimalFormat decimalFormatLong;
    private DecimalFormat exponentialFormat;
    private char groupSeparator;
    public NumberFormatter(int decimalPlaces) {
        configureDecimalPlaces(decimalPlaces);
    }
    public void configureDecimalPlaces(int decimalPlaces) {
        if (decimalPlaces <= 0) {
            throw new IllegalArgumentException("Invalid decimal places");
        }
        DecimalFormatSymbols separators = new DecimalFormatSymbols(Locale.getDefault());
        separators.setMinusSign(SYMBOL_MINUS);
        separators.setZeroDigit(SYMBOL_ZERO);
        groupSeparator = separators.getGroupingSeparator();
        StringBuilder decimal = new StringBuilder();
        StringBuilder exponential = new StringBuilder("0.");
        for (int i = 0; i < DECIMAL_LEADING_GROUPS; i++) {
            decimal.append("###").append(i == DECIMAL_LEADING_GROUPS - 1 ? "." : ",");
        }
        for (int i = 0; i < decimalPlaces; i++) {
            decimal.append("#");
            exponential.append("0");
        }
        exponential.append("E0");
        decimalFormat = new DecimalFormat(decimal.toString(), separators);
        decimalFormatLong = new DecimalFormat(decimal.append("####").toString(), separators);
        exponentialFormat = new DecimalFormat(exponential.toString(), separators);
        decimalFormat.setRoundingMode(RoundingMode.HALF_UP);
        decimalFormatLong.setRoundingMode(RoundingMode.HALF_UP);
        exponentialFormat.setRoundingMode(RoundingMode.HALF_UP);
    }
    public String format(double value) {
        String result;
        if (Double.isNaN(value)) {
            result = "";
        } else if (Double.isInfinite(value)) {
            result = String.valueOf(SYMBOL_INFINITE);
        } else {
            double absValue = Math.abs(value);
            if (absValue >= 1) {
                if (absValue >= EXPONENTIAL_INT_THRESHOLD) {
                    value = Math.floor(value);
                    result = exponentialFormat.format(value);
                } else {
                    result = decimalFormat.format(value);
                }
            } else if (absValue < 1 && absValue > 0) {
                if (absValue >= EXPONENTIAL_DEC_THRESHOLD) {
                    result = decimalFormat.format(value);
                    if (result.equalsIgnoreCase("0")) {
                        result = decimalFormatLong.format(value);
                    }
                } else {
                    result = exponentialFormat.format(value);
                }
            } else {
                result = "0";
            }
        }
        return result;
    }
    public String formatWithoutGroupSeparators(double value) {
        return removeGroupSeparators(format(value));
    }
    public double parse(String value, double defValue) {
        try {
            return decimalFormat.parse(value).doubleValue();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return defValue;
    }
    private String removeGroupSeparators(String number) {
        return number.replace(String.valueOf(groupSeparator), "");
    }
}

Antwoord 17

Om dit te bereiken kunnen we deze formatter gebruiken:

DecimalFormat df = new DecimalFormat("#.00");
 String resultado = df.format(valor)

of:

DecimalFormat df = new DecimalFormat("0.00"); :

Gebruik deze methode om altijd twee decimalen te krijgen:

  private static String getTwoDecimals(double value){
      DecimalFormat df = new DecimalFormat("0.00"); 
      return df.format(value);
    }

Deze waarden definiëren:

91.32
5.22
11.5
1.2
2.6

Met behulp van de methode kunnen we deze resultaten krijgen:

91.32
5.22
11.50
1.20
2.60

demo online.


Antwoord 18

Voor het geval iemand hier nog hulp bij nodig heeft. Deze oplossing werkt perfect voor mij.

private String withNoTrailingZeros(final double value, final int nrOfDecimals) {
return new BigDecimal(String.valueOf(value)).setScale(nrOfDecimals,  BigDecimal.ROUND_HALF_UP).stripTrailingZeros().toPlainString();
}

retourneert een String met de gewenste uitvoer.


Antwoord 19

Ik ga akkoord met het gekozen antwoord om DecimalFormat— of als alternatief BigDecimalte gebruiken.

Lees eerst Updatehieronder!

Als u echter doede dubbele waarde wilt afronden en een doublewaarde krijgt, kunt u org.apache.commons.math3.util.Precision.round(..)zoals hierboven vermeld. De implementatie gebruikt BigDecimal, is traag en zorgt voor rommel.


Een vergelijkbare maar snelle en afvalvrije methode wordt geleverd door het hulpprogramma DoubleRounderin de decimal4j-bibliotheek:

double a = DoubleRounder.round(2.0/3.0, 3);
 double b = DoubleRounder.round(2.0/3.0, 3, RoundingMode.DOWN);
 double c = DoubleRounder.round(1000.0d, 17);
 double d = DoubleRounder.round(90080070060.1d, 9);
 System.out.println(a);
 System.out.println(b);
 System.out.println(c);
 System.out.println(d);

Zal uitvoeren

0.667
 0.666
 1000.0
 9.00800700601E10

Zie
https://github.com/tools4j/decimal4j/wiki/DoubleRounder-Utility

Disclaimer:ik ben betrokken bij het decimal4j-project.

Bijwerken:
Zoals @iaforek opmerkte, geeft DoubleRounder soms contra-intuïtieve resultaten. De reden is dat het wiskundig correcte afrondingen uitvoert. DoubleRounder.round(256.025d, 2)wordt bijvoorbeeld naar beneden afgerond op 256.02 omdat de dubbele waarde die wordt weergegeven als 256.025d iets kleiner is dan de rationale waarde 256.025 en daarom naar beneden wordt afgerond.

Opmerkingen:

  • Dit gedrag lijkt erg op dat van de BigDecimal(double)-constructor (maar niet op valueOf(double)die de tekenreeksconstructor gebruikt).
  • Het probleem kan worden omzeild met een dubbele afrondingsstap naar een hogere precisie, maar het is ingewikkeld en ik ga hier niet in op de details

Om deze redenen en alles wat hierboven in dit bericht is vermeld, kan ik het gebruik van DoubleRounder niet aanbevelen.


Antwoord 20

Ik kwam hier omdat ik een eenvoudig antwoord wilde hebben over hoe je een getal moet afronden. Dit is een aanvullend antwoord om dat te bieden.

Hoe een getal in Java af te ronden

Het meest voorkomende geval is om Math.round()te gebruiken.

Math.round(3.7) // 4

Getallen worden afgerond op het dichtstbijzijnde gehele getal. Een waarde van .5wordt naar boven afgerond. Als u ander afrondingsgedrag nodig heeft, kunt u een van de andere Wiskundefuncties. Zie de vergelijking hieronder.

ronde

Zoals hierboven vermeld, deze rondes naar het dichtstbijzijnde hele getal. .5decimalen afronden Deze methode retourneert een int.

Math.round(3.0); // 3
Math.round(3.1); // 3
Math.round(3.5); // 4
Math.round(3.9); // 4
Math.round(-3.0); // -3
Math.round(-3.1); // -3
Math.round(-3.5); // -3 *** careful here ***
Math.round(-3.9); // -4

CEIL

Elke decimale waarde is afgerond op het volgende gehele getal. Het gaat naar de Ceil ING. Deze methode retourneert een double.

Math.ceil(3.0); // 3.0
Math.ceil(3.1); // 4.0
Math.ceil(3.5); // 4.0
Math.ceil(3.9); // 4.0
Math.ceil(-3.0); // -3.0
Math.ceil(-3.1); // -3.0
Math.ceil(-3.5); // -3.0
Math.ceil(-3.9); // -3.0

vloer

Elke decimale waarde wordt afgerond op het volgende gehele getal. Deze methode retourneert een double.

Math.floor(3.0); // 3.0
Math.floor(3.1); // 3.0
Math.floor(3.5); // 3.0
Math.floor(3.9); // 3.0
Math.floor(-3.0); // -3.0
Math.floor(-3.1); // -4.0
Math.floor(-3.5); // -4.0
Math.floor(-3.9); // -4.0

rint

Dit is vergelijkbaar met afronden waarbij decimale waarden worden afgerond op het dichtstbijzijnde gehele getal. Echter, in tegenstelling tot round, ronden .5waarden af op het even gehele getal. Deze methode retourneert een double.

Math.rint(3.0); // 3.0
Math.rint(3.1); // 3.0
Math.rint(3.5); // 4.0 ***
Math.rint(3.9); // 4.0
Math.rint(4.5); // 4.0 ***
Math.rint(5.5); // 6.0 ***
Math.rint(-3.0); // -3.0
Math.rint(-3.1); // -3.0
Math.rint(-3.5); // -4.0 ***
Math.rint(-3.9); // -4.0
Math.rint(-4.5); // -4.0 ***
Math.rint(-5.5); // -6.0 ***

Antwoord 21

Als je een technologie gebruikt met een minimale JDK. Hier is een manier zonder Java-bibliotheken:

double scale = 100000;    
double myVal = 0.912385;
double rounded = (int)((myVal * scale) + 0.5d) / scale;

Antwoord 22

Het onderstaande codefragment laat zien hoe n cijfers worden weergegeven. De truc is om variabele pp in te stellen op 1 gevolgd door n nullen. In het onderstaande voorbeeld heeft de variabele pp-waarde 5 nullen, dus er worden 5 cijfers weergegeven.

double pp = 10000;
double myVal = 22.268699999999967;
String needVal = "22.2687";
double i = (5.0/pp);
String format = "%10.4f";
String getVal = String.format(format,(Math.round((myVal +i)*pp)/pp)-i).trim();

Antwoord 23

Als je DecimalFormatgebruikt om doublenaar Stringte converteren, is dat heel eenvoudig:

DecimalFormat formatter = new DecimalFormat("0.0##");
formatter.setRoundingMode(RoundingMode.HALF_UP);
double num = 1.234567;
return formatter.format(num);

Er zijn verschillende RoundingMode-enumwaarden waaruit u kunt kiezen, afhankelijk van het gewenste gedrag.


Antwoord 24

DecimalFormat is de beste manier om uit te voeren, maar ik geef er de voorkeur aan. Ik doe dit altijd de hele tijd, omdat het de dubbele waarde retourneert. Dus ik kan het meer gebruiken dan alleen output.

Math.round(selfEvaluate*100000d.0)/100000d.0;

OF

Math.round(selfEvaluate*100000d.0)*0.00000d1;

Als u grote decimalen nodig heeft, kunt u in plaats daarvan BigDecimal gebruiken. Hoe dan ook, .0is belangrijk. Zonder dit is de afronding van 0.33333d5 0.33333 retour en zijn slechts 9 cijfers toegestaan. De tweede functie zonder .0heeft problemen met 0.30000 return 0.30000000000000004.


Antwoord 25

hier is mijn antwoord:

double num = 4.898979485566356;
DecimalFormat df = new DecimalFormat("#.##");      
time = Double.valueOf(df.format(num));
System.out.println(num); // 4.89

Antwoord 26

Ik heb balg gebruikt zoals in Java 8. het werkt voor mij

   double amount = 1000.431;        
    NumberFormat formatter = new DecimalFormat("##.00");
    String output = formatter.format(amount);
    System.out.println("output = " + output);

Uitvoer:

output = 1000.43

Antwoord 27

Hier is een betere functie die randgevallen zoals 1.005correct afrondt.

We tellen eenvoudigweg de kleinst mogelijke float-waarde (= 1 ulp; eenheid op de laatste plaats) op bij het getal voordat we afronden. Dit gaat naar de volgende representatieve waarde na het getal, weg van nul.

Dit is een klein programma om het te testen: ideone.com

/**
 * Round half away from zero ('commercial' rounding)
 * Uses correction to offset floating-point inaccuracies.
 * Works symmetrically for positive and negative numbers.
 */
public static double round(double num, int digits) {
    // epsilon correction
    double n = Double.longBitsToDouble(Double.doubleToLongBits(num) + 1);
    double p = Math.pow(10, digits);
    return Math.round(n * p) / p;
}
// test rounding of half
System.out.println(round(0.5, 0));   // 1
System.out.println(round(-0.5, 0));  // -1
// testing edge cases
System.out.println(round(1.005, 2));   // 1.01
System.out.println(round(2.175, 2));   // 2.18
System.out.println(round(5.015, 2));   // 5.02
System.out.println(round(-1.005, 2));  // -1.01
System.out.println(round(-2.175, 2));  // -2.18
System.out.println(round(-5.015, 2));  // -5.02

Antwoord 28

Dus na het lezen van de meeste antwoorden, realiseerde ik me dat de meeste niet precies zullen zijn, in feite lijkt het gebruik van BigDecimalde beste keuze, maar als je niet begrijpt hoe de RoundingModewerkt, verlies je onvermijdelijk precisie. Ik kwam hier achter toen ik met grote getallen in een project werkte en dacht dat het anderen zou kunnen helpen die problemen hebben met het afronden van getallen. Bijvoorbeeld.

BigDecimal bd = new BigDecimal("1363.2749");
bd = bd.setScale(2, RoundingMode.HALF_UP);
System.out.println(bd.doubleValue());

Je zou verwachten dat je 1363.28als uitvoer zou krijgen, maar je zult eindigen met 1363.27, wat niet verwacht wordt, als je niet weet wat de RoundingModedoet. Dus als je de Oracle Docsbekijkt, vindt u de volgende beschrijving voor RoundingMode.HALF_UP.

Afrondingsmodus om af te ronden naar “dichtstbijzijnde buur”, tenzij beide
buren liggen op gelijke afstand, in dat geval naar boven afronden.

Dus dit wetende, realiseerden we ons dat we geen exacte afronding krijgen, tenzij we willen afronden naar dichtstbijzijnde buur. Dus om een adequate ronde te bereiken, moeten we van het n-1decimaal naar de gewenste decimale cijfers lopen. Bijvoorbeeld.

private double round(double value, int places) throws IllegalArgumentException {
    if (places < 0) throw new IllegalArgumentException();
    // Cast the number to a String and then separate the decimals.
    String stringValue = Double.toString(value);
    String decimals = stringValue.split("\\.")[1];
    // Round all the way to the desired number.
    BigDecimal bd = new BigDecimal(stringValue);
    for (int i = decimals.length()-1; i >= places; i--) {
        bd = bd.setScale(i, RoundingMode.HALF_UP);
    }
    return bd.doubleValue();
}

Dit geeft ons uiteindelijk de verwachte output, die 1363.28zou zijn.


Antwoord 29

de volgende methode kan indien nodig worden gebruikt double

double getRandom(int decimalPoints) {
    double a = Math.random();
    int multiplier = (int) Math.pow(10, decimalPoints);
    int b = (int) (a * multiplier);
    return b / (double) multiplier;
}

bijvoorbeeld getRandom(2)

Other episodes