2016-03-25 9 views
6

मैं एक समारोह है कि जावा में एक सरल अंश के लिए एक double धर्मान्तरित बना दिया है:जांच करें कि एक डबल = 1/3

public static int gcm(int a, int b) { 
    return b == 0 ? a : gcm(b, a % b); 
} 
public static String toFraction(double d) { 
    int decimals = String.valueOf(d).split("\\.")[1].length(); 
    int mult = (int) Math.pow(10, decimals); 
    int numerator = (int) (d * mult); 
    int denominator = mult; 
    // now simplify 
    int gcm = gcm(numerator, denominator); 
    numerator /= gcm; 
    denominator /= gcm; 
    return numerator + "/" + denominator; 
} 

यह काम करता है, इस तथ्य के अलावा कि अगर मैं toFraction(1.0/3) उपयोग करते हैं, इस वसीयत, समझ में, "715827882/2147483647" लौटें। "1/3" वापस करने के लिए मैं इसे कैसे ठीक कर सकता हूं?

+1

@MickMnemonic BigDecimal कैसे प्रतिनिधित्व त्रुटि के बिना 1/3 का प्रतिनिधित्व करेगा? –

+2

मुझे नहीं पता कि यह दृष्टिकोण कैसे काम करेगा। एक डबल दशमलव नहीं है, और न ही यह मदद करेगा अगर यह था। क्या आप अन्य समाधानों के लिए खुले हैं? –

+0

सहमत हुए। ओपी को BigDecimal या कुछ समान का उपयोग करना चाहिए। – pczeus

उत्तर

6

आपको एक निश्चित त्रुटि की अनुमति देनी है और सभी भिन्नताओं को स्केलर मानों के रूप में बिल्कुल सही नहीं माना जा सकता है।

public static String toFraction(double d, double err) { 
    String s = Long.toString((long) d); 
    d -= (long) d; 
    if (d > err) { 
     for (int den = 2, max = (int) (1/err); den < max; den++) { 
      long num = Math.round(d * den); 
      double d2 = (double) num/den; 
      if (Math.abs(d - d2) <= err) 
       return (s.equals("0") ? "" : s + " ") + num +"/"+den; 
     } 
    } 
    return s; 
} 

public static void main(String... args) { 
    System.out.println(toFraction(1.0/3, 1e-6)); 
    System.out.println(toFraction(1.23456789, 1e-6)); 
    System.out.println(toFraction(Math.E, 1e-6)); 
    System.out.println(toFraction(Math.PI, 1e-6)); 
    for (double d = 10; d < 1e15; d *= 10) 
     System.out.println(toFraction(Math.PI, 1.0/d)); 
} 

प्रिंट

1/3 
1 19/81 
2 719/1001 
3 16/113 
3 1/5 
3 1/7 
3 9/64 
3 15/106 
3 16/113 
3 16/113 
3 3423/24175 
3 4543/32085 
3 4687/33102 
3 14093/99532 
3 37576/265381 
3 192583/1360120 
3 244252/1725033 
3 2635103/18610450 

नोट: इस पीआई के लिए 21/7, 333/106 और 355/113 अनुमानों पाता है।

+1

समस्या प्रिंटिंग फ्लोटिंग पॉइंट्स से अत्यधिक संबंधित प्रतीत होती है। मुझे आश्चर्य है कि क्या आप एक ही grisu3 रणनीति का उपयोग कर सकते हैं जो सबसे छोटी प्रिंट करने योग्य स्ट्रिंग पाती है जो फ्लोट के द्विआधारी प्रतिनिधित्व को वापस कर देगी। समस्या थोड़ी अलग है हालांकि: सबसे छोटे संप्रदाय के साथ अंश खोजें कि फ़्लोटिंग पॉइंट में कनवर्ट करने पर फ़्लोटिंग पॉइंट नंबर लौटाएगा। Grisu3 को ऐसा करने के लिए बिग्नम अंकगणित में वापस गिरने की जरूरत है हालांकि मामूली मामलों में। – JasonN

3

नहीं double मूल्य एक तिहाई के बराबर है, तो एक ही तरीका है अपने कार्यक्रम मुद्रित करने के लिए 1/3 यदि आप "अच्छा" के बजाय जवाब यह है कि तकनीकी रूप से सही है जवाब के पक्ष में विधि के विनिर्देश बदल है बनाया जा सकता है।

एक चीज जो आप कर सकते हैं, जवाब के लिए अधिकतम denominator चुनते हैं, 100 कहें, और 100 या उससे कम denominator के साथ निकटतम अंश वापस करें।

public static String toFraction(double val) { 
    int b = IntStream.rangeClosed(1, 100) 
        .boxed() 
        .min(Comparator.comparingDouble(n -> Math.abs(val * n - Math.round(val * n)))) 
        .get(); 
    int a = (int) Math.round(val * b); 
    int h = gcm(a, b); 
    return a/h + "/" + b/h; 
} 

इस के लिए कोई अच्छा तरीका है:

यहाँ कैसे आप इस का उपयोग कर जावा 8 धाराओं को लागू कर सकता है। double इस तरह की चीज़ के लिए बहुत अच्छा नहीं है। ध्यान दें कि BigDecimal 1/3 का प्रतिनिधित्व नहीं कर सकता है, इसलिए आपको उस वर्ग के साथ एक ही समस्या होगी।

0

इसे संभालने के अच्छे तरीके हैं लेकिन आपको विशेष मामलों को देखने की आवश्यकता होगी। उदाहरण के लिए, यदि संख्या 1 है तो अंश पहले से ही कम हो चुका है और आप बस दशमलव स्थानों को बाहर निकाल देते हैं और जो आपको दिया गया था उसे वापस कर देते हैं।

संबंधित मुद्दे