Αυτό το άρθρο είναι ένα άρθρο καθρέφτη της αυτόματης μετάφρασης, κάντε κλικ εδώ για να μεταβείτε στο αρχικό άρθρο.

Άποψη: 17373|Απάντηση: 0

[Πηγή] java.math.BigDecimal κλάση

[Αντιγραφή συνδέσμου]
Δημοσιεύτηκε στις 7/4/2015 2:53:05 μ.μ. | | |

Οι λειτουργίας για μεγάλους αριθμούς παρέχονται σε java, δηλαδή η κλάση java.math.BinInteger και η κλάση java.math.BigDecibal. Αυτές οι δύο χρησιμοποιούνται για υπολογιστές υψηλής ακρίβειας, με την κλάση BigInteger να είναι η κλάση επεξεργασίας για μεγάλους ακέραιους αριθμούς και την κλάση BigDecimal να είναι η κλάση επεξεργασίας για μεγάλους και μικρούς αριθμούς. Παρακάτω παρουσιάζουμε την κλάση BigDecimal:
Η υλοποίηση του BigDecimal εκμεταλλεύεται το BigInteger, με τη διαφορά ότι το BigDecimal προσθέτει την έννοια των δεκαδικών. Τα γενικά δεδομένα float και διπλού τύπου μπορούν να χρησιμοποιηθούν μόνο για επιστημονικούς υπολογισμούς ή μηχανικούς υπολογισμούς, επειδή στους εμπορικούς υπολογιστές, η απαιτούμενη αριθμητική ακρίβεια είναι σχετικά υψηλή, επομένως χρησιμοποιείται η κλάση java.math.BigDecibal, η οποία υποστηρίζει οποιαδήποτε ακρίβεια σταθερών σημείων και μπορεί να χρησιμοποιηθεί για τον ακριβή υπολογισμό των τιμών των νομισμάτων. Παρακάτω θα παρουσιάσουμε εν συντομία τη χρήση του με παραδείγματα

java.math.BigDecimal

Σήμερα, έγραψα ένα πρόγραμμα για τη δυαδική και δεκαδική μετατροπή με αναφορά στο σχολικό βιβλίο και ο αλγόριθμος του προγράμματος δεν είναι δύσκολος, αλλά αφού έγραψα, διαπίστωσα ότι είτε είναι 2 προς 10 είτε 10 προς 2, δεν είναι καλή μετατροπή για αριθμούς μεγαλύτερους από 2,1 δισεκατομμύρια, δηλαδή περισσότερο από το ακέραιο εύρος. θα γίνει 0.
Τα βιβλία αναφοράς έχουν διαπιστώσει ότι η χρήση του BigInteger λύνει αυτό το πρόβλημα.
Έψαξα λοιπόν το JDK και μετά το δοκίμασα αρκετές φορές και τελικά το έγραψα με επιτυχία!
Η εμπειρία χρήσης είναι η εξής:

1. Το BigInteger ανήκει στο java.math.BigInteger, επομένως εισάγετε αυτήν την κλάση πριν από κάθε χρήση. Περιστασιακά, ξέχασα να εισάγω στην αρχή, οπότε η προτροπή δεν μπορεί να βρεθεί στη συνεχή προτροπή.

2. Υπάρχουν πολλές μέθοδοι κατασκευής, αλλά τώρα χρησιμοποιούνται περιστασιακά:
BigInteger(Συμβολοσειρά)
          Μετατρέψτε την αναπαράσταση δεκαδικής συμβολοσειράς του BigInteger σε BigInteger.
BigInteger(Συμβολοσειρά val, int radix)
          Μετατρέπει την αναπαράσταση συμβολοσειράς του BigInteger για την καθορισμένη πληθικότητα σε BigInteger.
Για να μετατρέψετε 2 του τύπου int σε τύπο BigInteger, γράψτε BigInteger two=new BigInteger("2"); Σημείωση 2 Τα διπλά εισαγωγικά δεν μπορούν να παραλειφθούν

3. Η κλάση BigInteger προσομοιώνει όλες τις μαθηματικές πράξεις τύπου int, όπως add()=="+", divide()=="-", κ.λπ., αλλά σημειώστε ότι το περιεχόμενό της δεν μπορεί να χρησιμοποιηθεί απευθείας για μαθηματικές πράξεις κατά την εκτέλεση μαθηματικών πράξεων και πρέπει να χρησιμοποιεί τις εσωτερικές της μεθόδους. Και ο τελεστής του πρέπει επίσης να είναι τύπου BigInteger.
Για παράδειγμα: two.add(2) είναι μια λανθασμένη πράξη επειδή το 2 δεν γίνεται τύπος BigInteger .

4. Όταν θέλετε να εξάγετε τα αποτελέσματα υπολογισμού, θα πρέπει να χρησιμοποιήσετε τη μέθοδο .toString για να τη μετατρέψετε σε δεκαδική συμβολοσειρά, όπως περιγράφεται ως εξής:
String toString()
          Επιστρέφει την αναπαράσταση δεκαδικής συμβολοσειράς αυτού του BigInteger.
Μέθοδος εξόδου: System.out.print(two.toString());

5. Εξηγήστε τις τρεις λειτουργίες που χρησιμοποιούνται.   
BigInteger υπόλοιπο(BigInteger val)
          Επιστρέφει ένα BigInteger με τιμή (αυτό το % val).
BigInteger negate()
          Το BigInteger επιστρέφει μια τιμή (-this).
int compareTo(BigInteger val)
          Συγκρίνετε αυτόν τον BigInteger με τον καθορισμένο BigInteger.
υπόλοιποχρησιμοποιείται για την εύρεση του υπολοίπου.
Η άρνηση μετατρέπει τον τελεστέο στο αντίθετο.
Η σύγκριση εξηγείται λεπτομερώς ως εξής:
συγκρίνωΜε

public int compareTo(BigInteger val)

    Συγκρίνετε αυτόν τον BigInteger με τον καθορισμένο BigInteger. Αυτή η μέθοδος προτιμάται για καθέναν από τους έξι τελεστές σύγκρισης Boolean (<, ==, >, >=, !=, <=). Η προτεινόμενη πρόταση για την εκτέλεση αυτών των συγκρίσεων είναι: (x.compareTo(y) <op> 0), όπου είναι <op> ένας από τους έξι τελεστές σύγκρισης.

     

    Προσδιοριστής:
        διεπαφή<BigInteger> Συγκρίσιμη

    Παράμετροι:
        val - Ο BigInteger που συγκρίνει αυτόν τον BigInteger με αυτόν.
    Πίσω:

   
  Τίτλος Εφαρμογή ακριβών υπολογισμών αριθμών κινητής υποδιαστολής σε Java AYellow (Αρχική) Τροποποίηση           
  Λέξεις-κλειδιά Ακριβής υπολογισμός αριθμού κινητής υποδιαστολής Java         
   
   
  Ερώτηση:   
  Τι θα βλέπαμε αν μεταγλωττίζαμε και εκτελούσαμε το παρακάτω πρόγραμμα;   
  Τεστ δημόσιας τάξης{   
          public static void main(String args[]){   
                  System.out.println(0,05+0,01);   
                  System.out.println(1.0-0.42);   
                  System.out.println(4.015*100);   
                  System.out.println(123.3/100);   
          }   
  };   
   
  Καλά διαβάσατε! Το αποτέλεσμα είναι, πράγματι,   
  0.060000000000000005   
  0.5800000000000001   
  401.49999999999994   
  1.2329999999999999   
   
  Δεν είναι δυνατή η λειτουργία απλών float και διπλών τύπων σε Java. Αυτό το πρόβλημα δεν εντοπίζεται μόνο στην Java, αλλά και σε πολλές άλλες γλώσσες προγραμματισμού. Στις περισσότερες περιπτώσεις, οι υπολογισμοί είναι ακριβείς, αλλά μπορείτε να δοκιμάσετε μερικές ακόμη φορές (μπορείτε να κάνετε έναν βρόχο) για να δοκιμάσετε σφάλματα όπως το παραπάνω. Τώρα επιτέλους καταλαβαίνω γιατί υπάρχει κωδικός BCD.   
  Αυτό το πρόβλημα είναι αρκετά σοβαρό, εάν έχετε 9,9999999999999999999 γιουάν, ο υπολογιστής σας δεν θα πιστεύει ότι μπορείτε να αγοράσετε αγαθά 10 γιουάν.   
  Ορισμένες γλώσσες προγραμματισμού παρέχουν εξειδικευμένους τύπους νομισμάτων για να χειριστούν αυτήν την κατάσταση, αλλά η Java όχι. Τώρα ας δούμε πώς να το διορθώσετε.   
   
      
   
  Στρογγυλοποίηση   
  Η πρώτη μας αντίδραση είναι να κάνουμε στρογγυλοποίηση. Η στρογγυλή μέθοδος στο μάθημα των Μαθηματικών δεν μπορεί να ρυθμιστεί ώστε να διατηρεί μερικά δεκαδικά ψηφία, μπορούμε να κάνουμε μόνο αυτό (να κρατήσουμε δύο θέσεις):   
  δημόσιος διπλός γύρος(διπλή τιμή){   
          επιστροφή Math.round(τιμή*100)/100.0;   
  }   
   
  Δυστυχώς, ο παραπάνω κωδικός δεν λειτουργεί, περνώντας το 4.015 σε αυτή τη μέθοδο θα επιστρέψει 4.01 αντί για 4.02, όπως είδαμε παραπάνω   
  4.015*100=401.49999999999994   
  Επομένως, εάν θέλουμε να κάνουμε ακριβή στρογγυλοποίηση, δεν μπορούμε να χρησιμοποιήσουμε απλούς τύπους για να κάνουμε οποιεσδήποτε λειτουργίες   
  Το java.text.DecimalFormat δεν λύνει ούτε αυτό το πρόβλημα:   
  System.out.println(new java.text.DecimalFormat("0.00").format(4.025));   
  Η έξοδος είναι 4.02   
   
      
   
  ΜεγάλοΔεκαδικό   
  Αυτή η αρχή αναφέρεται επίσης στο βιβλίο "Effective Java", το float και το double μπορούν να χρησιμοποιηθούν μόνο για επιστημονικούς ή μηχανικούς υπολογισμούς και στους επιχειρηματικούς υπολογιστές πρέπει να χρησιμοποιήσουμε java.math.BigDecimal. Υπάρχουν 4 τρόποι για να φτιάξετε το BigDecimal, δεν μας ενδιαφέρουν οι δύο που είναι φτιαγμένοι με το BigInteger, επομένως υπάρχουν άλλοι δύο, οι οποίοι είναι:   
  BigDecimal (διπλή αξία)     
                      Μεταφράζει ένα διπλό σε BigDecimal.     
  BigDecimal (Αξία χορδών)     
                      Μεταφράζει την αναπαράσταση συμβολοσειράς ενός BigDecimal σε BigDecimal.   
   
  Το API περιγράφεται εν συντομία και είναι συνήθως πιο εύκολο στη χρήση. Μπορεί να το χρησιμοποιήσουμε χωρίς καν να το σκεφτούμε, ποιο θα είναι το πρόβλημα; Όταν κάτι πήγε στραβά, ανακάλυψα ότι υπήρχε μια τέτοια παράγραφος στη λεπτομερή περιγραφή του ποια από τις παραπάνω μεθόδους ήταν επαρκής:   
  Σημείωση: τα αποτελέσματα αυτού του κατασκευαστή μπορεί να είναι κάπως απρόβλεπτα.   Κάποιος θα μπορούσε να υποθέσει ότι το νέο BigDecimal(.1) είναι ακριβώς ίσο με .1, αλλά στην πραγματικότητα είναι ίσο με .1000000000000000055511151231257827021181583404541015625.   Αυτό συμβαίνει επειδή το .1 δεν μπορεί να αναπαρασταθεί ακριβώς ως διπλό (ή, για αυτό το θέμα, ως δυαδικό κλάσμα οποιουδήποτε πεπερασμένου μήκους).   Έτσι, η μεγάλη τιμή που μεταβιβάζεται στον κατασκευαστή δεν είναι ακριβώς ίση με .1, παρά τις εμφανίσεις.     
  Ο κατασκευαστής (String), από την άλλη πλευρά, είναι απόλυτα προβλέψιμος: το νέο BigDecimal (".1") είναι ακριβώς ίσο με το .1, όπως θα περίμενε κανείς.   Ως εκ τούτου, συνιστάται γενικά να χρησιμοποιείται ο κατασκευαστής (String) κατά προτίμηση από αυτόν.   
   
  Αποδεικνύεται ότι αν χρειαστεί να υπολογίσουμε με ακρίβεια, πρέπει να χρησιμοποιήσουμε το String για να δημιουργήσουμε το BigDecimal! Το παράδειγμα στο βιβλίο Effective Java χρησιμοποιεί το String για να δημιουργήσει το BigDecimal, αλλά το βιβλίο δεν το τονίζει αυτό, κάτι που μπορεί να είναι ένα μικρό λάθος.   
      
   
  Λύση   
  Τώρα που λύσαμε αυτό το πρόβλημα, η αρχή είναι να χρησιμοποιήσουμε το BigDecimal και να φροντίσουμε να χρησιμοποιήσουμε το String.   
  Φανταστείτε όμως αν θέλουμε να κάνουμε μια πράξη πρόσθεσης, πρέπει πρώτα να μετατρέψουμε δύο αριθμούς κινητής υποδιαστολής σε String, μετά να δημιουργήσουμε ένα BigDecimal, να καλέσουμε τη μέθοδο προσθήκης σε έναν από αυτούς, να περάσουμε τον άλλο ως όρισμα και μετά να μετατρέψουμε το αποτέλεσμα της πράξης (BigDecimal) σε αριθμό κινητής υποδιαστολής. Μπορείτε να αντέξετε μια τόσο κουραστική διαδικασία; Παρακάτω παρέχουμε μια κλάση εργαλείων Arith για να απλοποιήσουμε τη λειτουργία. Προσφέρει τις ακόλουθες στατικές μεθόδους, όπως πρόσθεση, αφαίρεση, πολλαπλασιασμό και διαίρεση και στρογγυλοποίηση:   
  Δημόσια στατική διπλή προσθήκη (Διπλή V1, Διπλή V2)   
  Δημόσιο Στατικό Διπλό Υποβρύχιο (Διπλό V1, Διπλό V2)   
  Δημόσιο στατικό διπλό mul (Διπλό V1, Διπλό V2)   
  δημόσιο στατικό διπλό div (διπλό v1, διπλό v2)   
  δημόσιο στατικό διπλό div (διπλό v1, διπλό v2, κλίμακα int)   
  Δημόσιος στατικός διπλός γύρος (διπλή κλίμακα V, Int)   
   
   
   
  Προσάρτημα   
   
   
  Πηγαίο αρχείο Arith.java:   
   
  εισαγωγή java.math.BigDecimal;   
  /**   
    * Δεδομένου ότι οι απλοί τύποι της Java δεν μπορούν να εκτελέσουν με ακρίβεια λειτουργίες κινητής υποδιαστολής, αυτή η κλάση εργαλείων παρέχει πρόστιμα   
    * Ακριβείς πράξεις κινητής υποδιαστολής, συμπεριλαμβανομένης της πρόσθεσης, της αφαίρεσης, του πολλαπλασιασμού, της διαίρεσης και της στρογγυλοποίησης.   
    */   
   
  δημόσια τάξη Arith{   
   
          Προεπιλεγμένη ακρίβεια λειτουργίας διαίρεσης   
          ιδιωτικό στατικό τελικό int DEF_DIV_SCALE = 10;   
   
   
          Αυτή η τάξη δεν μπορεί να δημιουργηθεί   
          ιδιωτική Arith(){   
          }   
   
      
          /**   
            * Παρέχει ακριβείς λειτουργίες προσθήκης.   
            * Προστίθεται @param v1   
            * @param προσθήκη v2   
            * @return Το άθροισμα των δύο παραμέτρων   
            */   
   
          δημόσια στατική διπλή προσθήκη (διπλή v1, διπλή v2){   
                  BigDecimal b1 = νέο BigDecimal(Double.toString(v1));   
                  BigDecimal b2 = νέο BigDecimal(Double.toString(v2));   
                  επιστροφή b1.add(b2).doubleValue();   
          }   
   
          /**   
            * Παρέχει ακριβείς πράξεις αφαίρεσης.   
            * @param v1 αφαιρείται   
            * @param v2 μείον   
            * @return Η διαφορά μεταξύ των δύο παραμέτρων   
            */   
   
          Δημόσιο στατικό διπλό sub(διπλό v1, διπλό v2){   
                  BigDecimal b1 = νέο BigDecimal(Double.toString(v1));   
                  BigDecimal b2 = νέο BigDecimal(Double.toString(v2));   
                  επιστροφή b1.subtract(b2).doubleValue();   
          }     
   
          /**   
            * Παρέχει ακριβείς πράξεις πολλαπλασιασμού.   
            * @param v1 πολλαπλασιάζεται   
            * @param πολλαπλασιαστής v2   
            * @return Το γινόμενο των δύο παραμέτρων   
            */   
   
          δημόσιο στατικό διπλό mul (διπλό v1, διπλό v2){   
                  BigDecimal b1 = νέο BigDecimal(Double.toString(v1));   
                  BigDecimal b2 = νέο BigDecimal(Double.toString(v2));   
                  επιστροφή b1.multiply(b2).doubleValue();   
          }   
   
      
   
          /**   
            * Παρέχει (σχετικά) ακριβείς λειτουργίες διαίρεσης, όταν συμβαίνει ανεξάντλητη διαίρεση   
            * 10 δεκαδικά ψηφία και τα ακόλουθα ψηφία στρογγυλοποιούνται.   
            * @param v1 είναι διαιρεμένο   
            * @param διαιρέτης v2   
            * @return Το πηλίκο των δύο παραμέτρων   
            */   
   
          δημόσιο στατικό διπλό div (διπλό v1, διπλό v2){   
                  επιστροφή div(v1,v2,DEF_DIV_SCALE);   
          }   
   
      
   
          /**   
            * Παρέχει (σχετικά) ακριβείς λειτουργίες διαίρεσης. Όταν συμβαίνει μια ανεξάντλητη κατάσταση, υποδεικνύεται από την παράμετρο της κλίμακας   
            * Προσδιορίστε την ακρίβεια και οι αριθμοί μετά από αυτήν θα στρογγυλοποιηθούν.   
            * @param v1 είναι διαιρεμένο   
            * @param διαιρέτης v2   
            * @param κλίμακα υποδεικνύει ότι πρέπει να είναι ακριβής με μερικά δεκαδικά ψηφία.   
            * @return Το πηλίκο των δύο παραμέτρων   
            */   
   
          δημόσιο στατικό διπλό div (διπλό v1, διπλό v2, κλίμακα int){   
                  if(κλίμακα<0){   
                          ρίξε νέο IllegalArgumentException(   
                                  "Η κλίμακα πρέπει να είναι θετικός ακέραιος ή μηδέν");   
                  }   
                  BigDecimal b1 = νέο BigDecimal(Double.toString(v1));   
                  BigDecimal b2 = νέο BigDecimal(Double.toString(v2));   
                  επιστροφή b1.divide(b2,κλίμακα,BigDecimal.ROUND_HALF_UP).doubleValue();   
          }   
   
      
   
          /**   
            * Παρέχει ακριβή δεκαδική στρογγυλοποίηση.   
            * @param v απαιτεί στρογγυλοποίηση αριθμών   
            * @param κλίμακα δεσμεύεται μετά την υποδιαστολή   
            * @return Στρογγυλοποιημένα αποτελέσματα   
            */   
   
          δημόσιος στατικός διπλός γύρος (διπλή κλίμακα V, Int){   
                  if(κλίμακα<0){   
                          ρίξε νέο IllegalArgumentException(   
                                  "Η κλίμακα πρέπει να είναι θετικός ακέραιος ή μηδέν");   
                  }   
                  BigDecimal b = νέο BigDecimal(Double.toString(v));   
                  BigDecimal one = νέο BigDecimal("1");   
                  επιστροφή b.divide(one,scale,BigDecimal.ROUND_HALF_UP).doubleValue();   
          }   
  };




Προηγούμενος:Είναι καλύτερο να μην ορίσετε μια συμβολοσειρά με νόημα ως πρωτεύον κλειδί
Επόμενος:Διαφορές και συνδέσεις JDK, JRE, JVM
Αποκήρυξη:
Όλο το λογισμικό, το υλικό προγραμματισμού ή τα άρθρα που δημοσιεύονται από το Code Farmer Network προορίζονται μόνο για μαθησιακούς και ερευνητικούς σκοπούς. Το παραπάνω περιεχόμενο δεν θα χρησιμοποιηθεί για εμπορικούς ή παράνομους σκοπούς, άλλως οι χρήστες θα υποστούν όλες τις συνέπειες. Οι πληροφορίες σε αυτόν τον ιστότοπο προέρχονται από το Διαδίκτυο και οι διαφορές πνευματικών δικαιωμάτων δεν έχουν καμία σχέση με αυτόν τον ιστότοπο. Πρέπει να διαγράψετε εντελώς το παραπάνω περιεχόμενο από τον υπολογιστή σας εντός 24 ωρών από τη λήψη. Εάν σας αρέσει το πρόγραμμα, υποστηρίξτε γνήσιο λογισμικό, αγοράστε εγγραφή και λάβετε καλύτερες γνήσιες υπηρεσίες. Εάν υπάρχει οποιαδήποτε παραβίαση, επικοινωνήστε μαζί μας μέσω email.

Mail To:help@itsvse.com