जावा में डबल के साथ सटीक बनाए रखें


149
public class doublePrecision {
    public static void main(String[] args) {

        double total = 0;
        total += 5.6;
        total += 5.8;
        System.out.println(total);
    }
}

उपरोक्त कोड प्रिंट:

11.399999999999

मैं इसे सिर्फ प्रिंट करने के लिए कैसे प्राप्त करूंगा (या इसे इस प्रकार उपयोग कर सकता हूं) 11.4?


जवाबों:


151

जैसा कि दूसरों ने उल्लेख किया है, आप शायद BigDecimalकक्षा का उपयोग करना चाहते हैं , यदि आप 11.4 का सटीक प्रतिनिधित्व चाहते हैं।

अब, यह क्यों हो रहा है में थोड़ा स्पष्टीकरण:

floatऔर doubleजावा में आदिम प्रकार कर रहे हैं बिंदु चल नंबर, जहां नंबर एक अंश है और एक प्रतिपादक के एक द्विआधारी प्रतिनिधित्व के रूप में संग्रहीत किया जाता है।

विशेष रूप से, एक डबल-सटीक फ़्लोटिंग पॉइंट मान जैसे कि doubleप्रकार 64-बिट मान है, जहां:

  • 1 बिट संकेत (सकारात्मक या नकारात्मक) को दर्शाता है।
  • घातांक के लिए 11 बिट्स।
  • महत्वपूर्ण अंकों के लिए 52 बिट्स (द्विआधारी के रूप में आंशिक भाग)।

इन भागों को doubleएक मूल्य का प्रतिनिधित्व बनाने के लिए संयुक्त किया जाता है ।

(स्रोत: विकिपीडिया: दोहरी परिशुद्धता )

जावा में फ़्लोटिंग पॉइंट वैल्यू को कैसे नियंत्रित किया जाता है, इसके विस्तृत विवरण के लिए, अनुभाग 4.2.3 देखें : फ़्लोटिंग-पॉइंट प्रकार, प्रारूप और जावा भाषा विनिर्देश के मान

byte, char, int, longप्रकार कर रहे हैं निश्चित बिंदु संख्या है, जो संख्या का सही representions हैं। निश्चित बिंदु संख्याओं के विपरीत, फ्लोटिंग पॉइंट संख्या कुछ समय ("अधिकांश समय मानने के लिए सुरक्षित") एक संख्या के सटीक प्रतिनिधित्व को वापस करने में सक्षम नहीं होती है। यही कारण है कि आप 11.399999999999के परिणाम के रूप में समाप्त होता है 5.6 + 5.8

जब सही मान की आवश्यकता होती है, जैसे कि 1.5 या 150.1005, तो आप निश्चित-बिंदु प्रकारों में से एक का उपयोग करना चाहते हैं, जो कि वास्तव में संख्या का प्रतिनिधित्व करने में सक्षम होगा।

जैसा कि पहले ही कई बार उल्लेख किया जा चुका है, जावा में एक BigDecimalवर्ग है जो बहुत बड़ी संख्या और बहुत छोटी संख्या को संभालेगा।

BigDecimalकक्षा के लिए जावा एपीआई संदर्भ से :

अपरिवर्तनीय, मनमाना-सटीक हस्ताक्षरित दशमलव संख्या। एक BigDecimal में एक मनमाना सटीक पूर्णांक पूर्णांक रहित मान और 32-बिट पूर्णांक स्केल होता है। यदि शून्य या सकारात्मक है, तो स्केल दशमलव बिंदु के दाईं ओर अंकों की संख्या है। यदि ऋणात्मक है, तो पैमाने के नकारने की शक्ति के लिए संख्या का अनसुलझा मूल्य दस से गुणा किया जाता है। BigDecimal द्वारा दर्शाई गई संख्या का मान इसलिए (unscaledValue × 10 ^ -scale) है।

स्टैक ओवरफ्लो पर फ्लोटिंग पॉइंट नंबरों के मामले और इसकी शुद्धता से संबंधित कई सवाल किए गए हैं। यहाँ संबंधित प्रश्नों की एक सूची है जो ब्याज की हो सकती है:

यदि आप वास्तव में फ़्लोटिंग पॉइंट नंबरों के नॉटी ग्रिटि विवरण के लिए नीचे उतरना चाहते हैं, तो फ़्लोटिंग-पॉइंट अरिथमेटिक के बारे में क्या हर कंप्यूटर साइंटिस्ट को पता होना चाहिए


3
वास्तव में, आम तौर पर 53 महत्वपूर्ण बिट्स होते हैं क्योंकि 1 "दशमलव" बिंदु से पहले सभी को चिह्नित किया जाता है, लेकिन सभी मानों को अलग-अलग मानकर एक अतिरिक्त बिट देता है। उदाहरण 3 को (1.) 1000 ... x 2 ^ 1 के रूप में संग्रहीत किया जाता है, जबकि 0.5 को (1.) 0000 ... x 2 ^ -1 के रूप में संग्रहित किया जाता है। जब मान का निरूपण किया जाता है (सभी प्रतिपादक बिट शून्य होते हैं), और आम तौर पर कम महत्वपूर्ण अंक होंगे, जैसे 1 x 2 ^ -1030 को (0.) 00000001 x 2 ^ -1022 के रूप में संग्रहीत किया जाता है, इसलिए सात महत्वपूर्ण अंकों को पैमाने पर बलिदान किया गया है।
सारा फिलिप्स

1
यह ध्यान दिया जाना चाहिए कि इस मामले में BigDecimalबहुत धीमी है , जबकि इसकी doubleआवश्यकता नहीं है क्योंकि डबल में सटीकता के 15 दशमलव स्थान हैं, आपको बस राउंडिंग की आवश्यकता है।
पीटर लॉरी

2
@PeterLawrey इसकी सटीकता के 15 दशमलव अंक हैं, यदि वे सभी दशमलव बिंदु से पहले हैं । दशमलव और द्विआधारी अंशों की अक्षमता के कारण दशमलव बिंदु के बाद कुछ भी हो सकता है।
लोर्न

@ ईजेपी आप सही हैं, इसमें सटीक के लगभग 15 महत्वपूर्ण अंक हैं। यह 16 हो सकता है लेकिन यह मान लेना सुरक्षित है कि यह 15 है या शायद 14.
पीटर लॉरी

@PeterLawrey EJP का सुधार मेरे प्रश्न के कारण था: stackoverflow.com/questions/36344758/… क्या आप इसका विस्तार कर सकते हैं कि इसकी संख्या 15 क्यों नहीं है और यह 16 या 14 हो सकती है?
शिवम सिन्हा

103

जब आप एक डबल नंबर इनपुट करते हैं, उदाहरण के लिए, 33.33333333333333आपको जो मूल्य मिलता है, वह वास्तव में निकटतम प्रतिनिधित्व योग्य डबल-सटीक मूल्य है, जो वास्तव में है:

33.3333333333333285963817615993320941925048828125

विभाजित करके जो 100 देता है:

0.333333333333333285963817615993320941925048828125

जो एक डबल-सटीक संख्या के रूप में भी प्रतिनिधित्व करने योग्य नहीं है, इसलिए फिर से इसे निकटतम प्रतिनिधित्व योग्य मूल्य के लिए गोल किया जाता है, जो वास्तव में है:

0.3333333333333332593184650249895639717578887939453125

जब आप इस मूल्य को प्रिंट करते हैं, तो यह 17 दशमलव अंकों के लिए फिर से गोल हो जाता है , जिससे:

0.33333333333333326

114
जो कोई भी भविष्य में इसे पढ़ रहा है और इस बात से हैरान है कि इस प्रश्न का उत्तर से कोई लेना-देना नहीं है: कुछ मॉडरेटर ने इस प्रश्न का उत्तर देने का निर्णय लिया था, जिसका मैंने (और अन्य) ने उत्तर दिया था, बल्कि अलग-अलग, प्रश्न।
स्टीफन कैनन

आप सटीक दोहरे मूल्य को कैसे जानते हैं?
माइकल यवोरस्की

@mikeyaworski en.wikipedia.org/wiki/Double-preaches_floating-point_format डबल सटीक उदाहरण देखें
Jaydee

23

यदि आप केवल मानों को भिन्न के रूप में संसाधित करना चाहते हैं, तो आप एक अंश वर्ग और भाजक फ़ील्ड बना सकते हैं।

जोड़ने के लिए तरीके लिखें, घटाएँ, गुणा करें और विभाजित करें और साथ ही एक डबल विधि। इस तरह आप गणना के दौरान तैरने से बच सकते हैं।

संपादित करें: त्वरित कार्यान्वयन,

public class Fraction {

private int numerator;
private int denominator;

public Fraction(int n, int d){
    numerator = n;
    denominator = d;
}

public double toDouble(){
    return ((double)numerator)/((double)denominator);
}


public static Fraction add(Fraction a, Fraction b){
    if(a.denominator != b.denominator){
        double aTop = b.denominator * a.numerator;
        double bTop = a.denominator * b.numerator;
        return new Fraction(aTop + bTop, a.denominator * b.denominator);
    }
    else{
        return new Fraction(a.numerator + b.numerator, a.denominator);
    }
}

public static Fraction divide(Fraction a, Fraction b){
    return new Fraction(a.numerator * b.denominator, a.denominator * b.numerator);
}

public static Fraction multiply(Fraction a, Fraction b){
    return new Fraction(a.numerator * b.numerator, a.denominator * b.denominator);
}

public static Fraction subtract(Fraction a, Fraction b){
    if(a.denominator != b.denominator){
        double aTop = b.denominator * a.numerator;
        double bTop = a.denominator * b.numerator;
        return new Fraction(aTop-bTop, a.denominator*b.denominator);
    }
    else{
        return new Fraction(a.numerator - b.numerator, a.denominator);
    }
}

}

1
निश्चित रूप से numeratorऔर denominatorहोना चाहिए int? आप फ्लोटिंग-पॉइंट सटीक क्यों चाहते हैं?
समीर तलवार

लगता है कि यह वास्तव में आवश्यक नहीं है, लेकिन यह डबल फ़ंक्शन में कास्टिंग से बचता है ताकि कोड बेहतर तरीके से पढ़े।
वायरल शाह

5
वायरलशाह: यह गणितीय कार्यों से निपटने के दौरान संभावित रूप से फ्लोटिंग-पॉइंट त्रुटि का भी परिचय देता है। यह देखते हुए कि इस कवायद की बात यह है कि इससे बचने के लिए, इसे बदलना समझदारी है।
समीर तलवार

ऊपर समीर तलवार द्वारा बताए गए कारणों के लिए, युगल के बजाय ints का उपयोग करने का संपादन किया गया।
वायरल शाह

3
अंशों के इस कार्यान्वयन में समस्याएं हैं क्योंकि यह उन्हें सरलतम रूप में कम नहीं करता है। 2/3 * 1/2 दे 2/6 जहाँ आप वास्तव में चाहते हैं कि उत्तर 1/3 हो। आदर्श रूप से निर्माता में आप अंश और भाजक के gcd खोजना चाहते हैं और दोनों को विभाजित करते हैं।
सेलिक्स अल्बा

15

ध्यान रखें कि यदि आप सीमित-सटीक दशमलव अंकगणित का उपयोग करते हैं, तो आपको भी यही समस्या होगी, और 1/3: 0.333333333 * 3 के साथ सौदा करना चाहते हैं। 0.999999999 है, न कि 1.00000000।

दुर्भाग्य से, 5.6, 5.8 और 11.4 केवल बाइनरी में गोल संख्या नहीं हैं, क्योंकि वे पांचवीं शामिल हैं। इसलिए फ्लोट का प्रतिनिधित्व सटीक नहीं है, ठीक उसी तरह जैसे 0.3333 1/3 नहीं है।

यदि आपके द्वारा उपयोग किए जाने वाले सभी नंबर गैर-आवर्ती दशमलव हैं, और आप सटीक परिणाम चाहते हैं, तो BigDecimal का उपयोग करें। या जैसा कि अन्य लोगों ने कहा है, यदि आपके मूल्य इस अर्थ में पैसे की तरह हैं कि वे सभी 0.01, या 0.001 या कुछ और हैं, तो सब कुछ 10 की निश्चित शक्ति से गुणा करें और int या long का उपयोग करें (जोड़ और घटाव) तुच्छ: गुणा के लिए बाहर देखो)।

हालाँकि, यदि आप गणना के लिए बाइनरी से खुश हैं, लेकिन आप थोड़े मित्रवत प्रारूप में चीजों को प्रिंट करना चाहते हैं, तो प्रयास करें java.util.FormatterयाString.format । प्रारूप स्ट्रिंग में डबल की पूर्ण परिशुद्धता की तुलना में कम सटीक निर्दिष्ट करते हैं। 10 महत्वपूर्ण आंकड़ों के अनुसार, 11.399999999999 11.4 है, इसलिए परिणाम उन मामलों में लगभग सटीक और अधिक मानव-पठनीय होगा जहां बाइनरी परिणाम केवल कुछ दशमलव स्थानों की आवश्यकता वाले मूल्य के बहुत करीब है।

निर्दिष्ट करने की सटीकता इस बात पर थोड़ी निर्भर करती है कि आपने अपने नंबरों के साथ कितना गणित किया है - सामान्य तौर पर जितना अधिक आप करते हैं, उतनी ही त्रुटि जमा होगी, लेकिन कुछ एल्गोरिदम इसे दूसरों की तुलना में बहुत तेजी से जमा करते हैं (उन्हें "अस्थिर" कहा जाता है) गोलाई त्रुटियों के संबंध में "स्थिर" का विरोध किया)। यदि आप जो कुछ कर रहे हैं वह कुछ मूल्यों को जोड़ रहा है, तो मुझे लगता है कि परिशुद्धता के सिर्फ एक दशमलव स्थान को छोड़ने से चीजें सुलझ जाएंगी। प्रयोग।


3
नहीं, मौद्रिक मूल्यों के साथ दोहरे का उपयोग करें! आपको पैसे के साथ सटीकता की आवश्यकता है, इसके बजाय BigDecimal का उपयोग करें। अन्यथा, आपका उत्तर अच्छा है। किसी भी चीज के साथ आपको सटीकता की आवश्यकता होती है, BigDecimal का उपयोग करें, यदि परिशुद्धता उतना महत्वपूर्ण नहीं है, तो आप फ्लोट या डबल का उपयोग कर सकते हैं।
MetroidFan2002

1
यह सवाल अब बताता नहीं है कि पैसा शामिल है या नहीं। मैं विशेष रूप से BigDecimal या पूर्णांकों को पैसे के लिए उपयोग करने के लिए कहता हूं। समस्या क्या है?
स्टीव जेसप

1
और "पैसे के लिए डबल का उपयोग न करें" के बराबर है "बिगडेसिमल या तिहाई के लिए डबल का उपयोग न करें "। लेकिन कभी-कभी एक समस्या में विभाजन शामिल होता है, जिसमें सभी आधारों के सभी प्रमुख कारकों द्वारा विभाज्य नहीं होने वाले सभी मामले समान रूप से खराब होते हैं।
स्टीव जेसप

1
.9999 = 1 यदि आपकी परिशुद्धता 4 महत्वपूर्ण अंकों से कम है
ब्रायन लीह

9

यदि आप वास्तव में सटीक गणित की आवश्यकता है, तो आप जावा के जावा.math.BigDecimal वर्ग का उपयोग करना चाहते हैं। यहाँ BigDecimal के मामले पर Oracle / Sun का एक अच्छा लेख है । जब तक आप 1/3 का प्रतिनिधित्व नहीं कर सकते हैं जैसा कि किसी ने उल्लेख किया है, तो आप कर सकते हैं तय करने की शक्ति हैं कि आप कितना सटीक परिणाम चाहते हैं। setScale () आपका दोस्त है .. :)

ठीक है, क्योंकि मेरे पास इस समय मेरे हाथों पर बहुत अधिक समय है, एक कोड उदाहरण है जो आपके प्रश्न से संबंधित है:

import java.math.BigDecimal;
/**
 * Created by a wonderful programmer known as:
 * Vincent Stoessel
 * xaymaca@gmail.com
 * on Mar 17, 2010 at  11:05:16 PM
 */
public class BigUp {

    public static void main(String[] args) {
        BigDecimal first, second, result ;
        first = new BigDecimal("33.33333333333333")  ;
        second = new BigDecimal("100") ;
        result = first.divide(second);
        System.out.println("result is " + result);
       //will print : result is 0.3333333333333333


    }
}

और मेरी नई पसंदीदा भाषा, ग्रूवी को प्लग करने के लिए, यहाँ एक ही बात का एक उदाहरण है:

import java.math.BigDecimal

def  first =   new BigDecimal("33.33333333333333")
def second = new BigDecimal("100")


println "result is " + first/second   // will print: result is 0.33333333333333

5

बहुत यकीन है कि आप एक तीन लाइन उदाहरण में बना सकते हैं। :)

यदि आप सटीक सटीकता चाहते हैं, तो BigDecimal का उपयोग करें। अन्यथा, आप 10 ^ गुणा गुणा का उपयोग कर सकते हैं, जो भी सटीक आप चाहते हैं।


5

जैसा कि अन्य ने नोट किया है, सभी दशमलव मूल्यों को बाइनरी के रूप में नहीं दिखाया जा सकता है क्योंकि दशमलव 10 की शक्तियों पर आधारित है और बाइनरी दो की शक्तियों पर आधारित है।

यदि सटीक मायने रखता है, तो BigDecimal का उपयोग करें, लेकिन यदि आप केवल अनुकूल आउटपुट चाहते हैं:

System.out.printf("%.2f\n", total);

तुम्हे दूंगा:

11.40


5

आप नहीं कर सकते, क्योंकि 7.3 में बाइनरी में एक परिमित प्रतिनिधित्व नहीं है। निकटतम आप प्राप्त कर सकते हैं 2054767329987789/2 ** 48 = 7.3 + 1/1407374883553280।

आगे की व्याख्या के लिए http://docs.python.org/tutorial/floatingpoint.html पर एक नज़र डालें । (यह पायथन वेबसाइट पर है, लेकिन जावा और सी ++ में एक ही "समस्या" है।)

समाधान इस बात पर निर्भर करता है कि आपकी समस्या क्या है:

  • यदि ऐसा है कि आप उन सभी शोर अंकों को देखना पसंद नहीं करते हैं, तो अपनी स्ट्रिंग प्रारूपण को ठीक करें। 15 से अधिक महत्वपूर्ण अंक (या फ्लोट के लिए 7) प्रदर्शित न करें।
  • यदि यह है कि आपके नंबरों की अक्षमता "अगर" बयान जैसी चीजों को तोड़ रही है, तो आपको यह लिखना चाहिए कि क्या (x == 7.3) के बजाय (एब्स (7.3 - 7.3) <टॉलरेंस) है।
  • यदि आप पैसे के साथ काम कर रहे हैं, तो आप जो वास्तव में चाहते हैं वह दशमलव निश्चित बिंदु है। सेंट की एक पूर्णांक संख्या या जो भी आपकी मुद्रा की सबसे छोटी इकाई है, को स्टोर करें।
  • (बहुत अच्छा) अगर आपको सटीक के 53 से अधिक महत्वपूर्ण बिट्स (15-16 महत्वपूर्ण अंक) की आवश्यकता है, तो BigDecimal जैसे उच्च-सटीक फ़्लोटिंग-पॉइंट प्रकार का उपयोग करें।

7.3 बाइनरी में एक परिमित प्रतिनिधित्व नहीं हो सकता है, लेकिन मुझे यकीन है कि जब मैं C ++ में एक ही चीज़ की कोशिश करता हूं तो -7.3 प्राप्त करें
गलत तरीके से

2
गलत नाम: नहीं, आप नहीं। यह सिर्फ उस तरह से प्रदर्शित करता है। असली जवाब देखने के लिए "% .17g" प्रारूप (या बेहतर अभी तक, "% .51g") का उपयोग करें।
dan04

4
private void getRound() {
    // this is very simple and interesting 
    double a = 5, b = 3, c;
    c = a / b;
    System.out.println(" round  val is " + c);

    //  round  val is  :  1.6666666666666667
    // if you want to only two precision point with double we 
            //  can use formate option in String 
           // which takes 2 parameters one is formte specifier which 
           // shows dicimal places another double value 
    String s = String.format("%.2f", c);
    double val = Double.parseDouble(s);
    System.out.println(" val is :" + val);
    // now out put will be : val is :1.67
}

3

Java.math.BigDecimal का उपयोग करें

युगल आंतरिक रूप से द्विआधारी अंश होते हैं, इसलिए वे कभी-कभी दशमलव अंशों को सटीक दशमलव तक नहीं दिखा सकते हैं।


1
-1 नेत्रहीन BigDecimal की सिफारिश के लिए। यदि आपको वास्तव में दशमलव अंकगणित की आवश्यकता नहीं है (यानी, यदि आप धन के साथ गणना कर रहे हैं), तो बिगडिमल आपकी मदद नहीं करता है। यह आपकी सभी फ़्लोटिंग-पॉइंट त्रुटियों को हल नहीं करता है: आपको अभी भी 1/3 * 3 = 0.9999999999999999999999999999 और sqrt (2) ** 2 = 1.999999999999999999999999 पर निपटना होगा। इसके अलावा, BigDecimal एक विशाल गति दंड वहन करती है। इससे भी बदतर, क्योंकि जावा में ऑपरेटर की ओवरलोडिंग की कमी के कारण, आपको अपने सभी कोड को फिर से लिखना होगा।
dan04

2
@ dan04 - यदि आप पैसे के साथ गणना करते हैं तो इसमें अंतर्निहित त्रुटि को जानते हुए फ्लोटिंग प्रतिनिधित्व का उपयोग क्यों करें .... चूंकि सेंट का कोई अंश नहीं है आप दशमलव का उपयोग कर सकते हैं और अनुमानित डॉलर का उपयोग करने के बजाय सेंट की गणना कर सकते हैं। यदि आप वास्तव में प्रतिशत का अंश लंबे समय तक उपयोग करना चाहते हैं और हजारों सेंट की गणना करते हैं। इसके अलावा, ओपी ने अपरिमेय संख्याओं का कोई उल्लेख नहीं किया था, इसके बारे में वह चिंतित था। पोस्ट को ध्यान से पढ़ें और उत्तर देने से पहले समस्या को समझें, हो सकता है कि आप कुछ शर्मिंदगी से बच सकें।
न्यूटॉपियन

3
@ न्यूटोपियन: मुझे शर्मिंदा होने की कोई बात नहीं है। ओपी ने पैसे का कोई उल्लेख नहीं किया, न ही कोई संकेत दिया कि उनकी समस्या में कोई अंतर्निहित दशमलव है।
dan04

@ dan04 - नहीं, ओपी ने नहीं किया ... आपने किया और ब्लाइंडली ने संदर्भ राय से बाहर की पेशकश की, जो कि सबसे अधिक संभावना थी, एक बिल्कुल स्वीकार्य जवाब था जो प्रदान की गई विवरणों की खराब राशि को देखते हुए
न्यूऑपियन

2

सब कुछ 100 से गुणा करें और इसे लंबे समय तक सेंट के रूप में संग्रहीत करें।


2
@Draemon - अंतिम संपादन से पहले पोस्ट देखें - वह सब "शॉपिंगटोटल" और "कैल्कगस्ट" और "कैल्कस्पस्ट" सामान मुझे पैसे की तरह लगता है।
पॉल टॉम्बलिन

2

कंप्यूटर बाइनरी में नंबर स्टोर करते हैं और वास्तव में 33.333333333 या 100.0 जैसे नंबर का प्रतिनिधित्व नहीं कर सकते हैं। यह युगल का उपयोग करने के बारे में मुश्किल चीजों में से एक है। उपयोगकर्ता को दिखाने से पहले आपको केवल उत्तर देना होगा। ज्यादातर अनुप्रयोगों में सौभाग्य से, आपको किसी भी तरह से कई दशमलव स्थानों की आवश्यकता नहीं है।


मैं कुछ बाधाओं की गणना कर रहा हूं जो मुझे सबसे अधिक सटीक संभव होगा। लेकिन मैं समझता हूं कि सीमाएँ हैं
एली

2

फ़्लोटिंग पॉइंट संख्या वास्तविक संख्याओं से भिन्न होती है जिसमें किसी दिए गए फ़्लोटिंग पॉइंट नंबर के लिए अगला उच्च फ़्लोटिंग पॉइंट नंबर होता है। पूर्णांक के रूप में भी। 1 और 2 के बीच कोई पूर्णांक नहीं है।

फ्लोट के रूप में 1/3 का प्रतिनिधित्व करने का कोई तरीका नहीं है। इसके नीचे एक फ्लोट है और इसके ऊपर एक फ्लोट है, और उनके बीच एक निश्चित दूरी है। और 1/3 उस जगह पर है।

जावा के लिए Apfloat मनमाने ढंग से सटीक फ्लोटिंग पॉइंट नंबरों के साथ काम करने का दावा करता है, लेकिन मैंने कभी इसका उपयोग नहीं किया है। शायद देखने लायक है। http://www.apfloat.org/apfloat_java/

जावा फ्लोटिंग पॉइंट हाई प्रिसिजन लाइब्रेरी से पहले इसी तरह का सवाल यहाँ पूछा गया था


1

डबल्स आपके जावा स्रोत में दशमलव संख्याओं के सन्निकटन हैं । आप दोहरे (जो एक द्वि-कोडित मान है) और आपके स्रोत (जो दशमलव-कोडित है) के बीच बेमेल का परिणाम देख रहे हैं।

जावा के निकटतम बाइनरी सन्निकटन का उत्पादन कर रहा है। आप बेहतर दिखने वाले दशमलव मान को प्रदर्शित करने के लिए java.text.DecimalFormat का उपयोग कर सकते हैं।


1

एक BigDecimal का उपयोग करें। यह आपको राउंडिंग नियम भी निर्दिष्ट करता है (जैसे ROUND_HALF_EVEN, जो दोनों समान दूरी होने पर भी पड़ोसी को राउंड करके सांख्यिकीय त्रुटि को कम करेगा; अर्थात दोनों 1.5 और 2.5 राउंड 2)।


1

संक्षिप्त उत्तर: हमेशा बिगडेसिमल का उपयोग करें और सुनिश्चित करें कि आप स्ट्रिंग तर्क के साथ कंस्ट्रक्टर का उपयोग कर रहे हैं , न कि डबल।

अपने उदाहरण पर वापस, निम्न कोड 11.4 प्रिंट होगा, जैसा आप चाहते हैं।

public class doublePrecision {
    public static void main(String[] args) {
      BigDecimal total = new BigDecimal("0");
      total = total.add(new BigDecimal("5.6"));
      total = total.add(new BigDecimal("5.8"));
      System.out.println(total);
    }
}

0

BigDecimal की जाँच करें, यह उस तरह फ्लोटिंग पॉइंट अंकगणित से निपटने में समस्याओं को संभालता है।

नई कॉल इस तरह दिखाई देगी:

term[number].coefficient.add(co);

उपयोग की जाने वाली दशमलव स्थान परिशुद्धता की संख्या निर्धारित करने के लिए setScale () का उपयोग करें।


0

गणित वर्ग से राउंड () पद्धति का उपयोग क्यों नहीं किया जाता है?

// The number of 0s determines how many digits you want after the floating point
// (here one digit)
total = (double)Math.round(total * 10) / 10;
System.out.println(total); // prints 11.4

0

यदि आपके पास दोहरे मानों का उपयोग करने के अलावा कोई विकल्प नहीं है, तो नीचे दिए गए कोड का उपयोग कर सकते हैं।

public static double sumDouble(double value1, double value2) {
    double sum = 0.0;
    String value1Str = Double.toString(value1);
    int decimalIndex = value1Str.indexOf(".");
    int value1Precision = 0;
    if (decimalIndex != -1) {
        value1Precision = (value1Str.length() - 1) - decimalIndex;
    }

    String value2Str = Double.toString(value2);
    decimalIndex = value2Str.indexOf(".");
    int value2Precision = 0;
    if (decimalIndex != -1) {
        value2Precision = (value2Str.length() - 1) - decimalIndex;
    }

    int maxPrecision = value1Precision > value2Precision ? value1Precision : value2Precision;
    sum = value1 + value2;
    String s = String.format("%." + maxPrecision + "f", sum);
    sum = Double.parseDouble(s);
    return sum;
}

-1

BigDecimal का उपयोग करके अपने अपशिष्ट को बर्बाद न करें। 99.99999% मामलों में आपको इसकी आवश्यकता नहीं है। जावा डबल प्रकार आंगन अनुमानित है, लेकिन लगभग सभी मामलों में, यह पर्याप्त रूप से सटीक है। मन करें कि आपकी 14 वीं महत्वपूर्ण अंक में त्रुटि है।यह वास्तव में नगण्य है!

अच्छा उत्पादन उपयोग प्राप्त करने के लिए:

System.out.printf("%.2f\n", total);

2
मुझे लगता है कि वह आउटपुट से चिंतित है, न कि संख्यात्मक परिशुद्धता से। और अगर आप उदाहरण के लिए BigDecimal कोई मदद नहीं करेगा। तीन से विभाजित करें। इससे हालात और भी खराब हो सकते हैं ...
मैकिक डी।

आपको कभी भी पैसे के लिए फ्लोटिंग-पॉइंट का इस्तेमाल कभी नहीं करना चाहिए। मैंने एक ठेकेदार पर लागू किए गए बड़े काम को देखा है, जो इस निर्देश के बावजूद इस नियम को तोड़ दिया।
लोर्ने
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.