2008-12-18 21 views
7

क्या कोई ऐसी लाइब्रेरी है जो पूरे नंबर के साथ डबल से स्ट्रिंग को परिवर्तित करेगी, उसके बाद एक अंश के बाद?प्रारूप के रूप में डबल प्रारूप

उदाहरण

1.125 = 1 1/8 

के लिए मैं केवल एक इंच के एक 64 वीं करने के लिए भिन्न के लिए देख रहा हूँ।

उत्तर

5

एक समस्या जो आप चला सकते हैं वह यह है कि सभी fractional मानों को युगल द्वारा प्रदर्शित नहीं किया जा सकता है। यहां तक ​​कि कुछ मान जो साधारण दिखते हैं, जैसे 0.1। अब छद्म कोड एल्गोरिदम के साथ। आप शायद एक इंच के 64 वें नंबर की संख्या निर्धारित करने से सबसे अच्छे होंगे, लेकिन दशमलव भाग को 0.015625 तक विभाजित करेंगे। इसके बाद, आप अपने अंश को सबसे कम आम denominator में कम कर सकते हैं। हालांकि, चूंकि आप इंच बताते हैं, तो आप सबसे छोटे आम ​​denominator का उपयोग नहीं करना चाहते हैं, बल्कि केवल वे मान हैं जिनके लिए आमतौर पर इंच का प्रतिनिधित्व किया जाता है, 2,4,8,16,32,64।

हालांकि, यह इंगित करने के लिए एक बात यह है कि चूंकि आप इंच का उपयोग कर रहे हैं, यदि मान एक इंच की सभी उचित भिन्नताएं हैं, तो 2,4,8,16,32,64 के संप्रदाय के साथ मूल्य कभी नहीं होना चाहिए फ्लोटिंग पॉइंट त्रुटियां होती हैं, क्योंकि denominator हमेशा 2 की शक्ति होती है। हालांकि यदि आपके डेटासेट में 1 इंच का मान था, तो आप समस्याओं में भागना शुरू कर देंगे।

+0

डेटा में आ रहा है अच्छा है (हमेशा एक इंच के 64ths में) – Milhous

3

मैं इस बात पर सहमत नहीं हूं कि मिल्शस 1/64 " तक इंच को कवर करना चाहता है मान लीजिए कि प्रोग्राम हर समय सटीकता 1/64" मांग करता है, जिसमें 6 बिट्स लेना चाहिए अपूर्णांश। एक फ्लोट में, 24-6 = 18 है, जो (यदि मेरा गणित सही है), इसका मतलब यह होना चाहिए कि उसे +/- 262144 + 63/64 "

की एक श्रृंखला मिली है जो कि फ्लोट में पर्याप्त सटीकता हो सकती है हानि के बिना गुट में ठीक से कनवर्ट करें।

और चूंकि ज्यादातर लोगों इंच पर काम कर 2 की शक्तियों के भाजक का उपयोग करता है, यह ठीक होना चाहिए।

लेकिन वापस मूल प्रश्न है, मैं किसी भी लाइब्रेरी नहीं पता है कि ऐसा करेंगे।

1

एलपीसी नामक सी-वेरिएंट में इसके लिए फ़ंक्शन निम्नानुसार है: कुछ नोट्स:

  1. शुरुआत में इनपुट मूल्य में वृद्धि सटीक मुद्दों से निपटने का प्रयास करना है जो अन्यथा आपको यह बताते हुए हवा से प्यार करते हैं कि 5 4 99 99 99/1000000 है।
  2. to_int() फ़ंक्शन पूर्णांक में छंटनी करता है।
  3. भाषा में एक to_string() है जो कुछ फ्लोट को घातीय नोटेशन में बदल देगा।

string strfrac(float frac) { 
    int main = to_int(frac + frac/1000000.0); 
    string out = to_string(main); 
    float rem = frac - to_float(main); 
    string rep; 
    if(rem > 0 && (to_int(rep = to_string(rem)) || member(rep, 'e') == Null)) { 
     int array primes = ({ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47 }); 
     string base; 
     int exp; 
     int num; 
     int div; 
     if(sscanf(rep, "%se%d", base, exp) == 2) { 
      num = to_int(replace(base, ".", "")); 
      div = to_int(pow(10, abs(exp))); 
     } else { 
      rep = rep[2..]; 
      num = to_int(rep); 
      div = to_int(pow(10, strlen(rep))); 
     } 
     foreach(int prime : primes) { 
      if(prime > num) 
       break; 
      while((num/prime) * prime == num && (div/prime) * prime == div) { 
       num /= prime; 
       div /= prime; 
      } 
     } 
     out += " " + num + "/" + div; 
    } 
    return out; 
} 
10

आपकी समस्या, बहुत सरल है, क्योंकि आप (किसी एक जावा संस्करण का अनुवाद करने के लिए स्वतंत्र महसूस) का आश्वासन दिया भाजक हमेशा सी # में 64 को विभाजित करेगा कर रहे हैं:

string ToMixedFraction(decimal x) 
{ 
    int whole = (int) x; 
    int denominator = 64; 
    int numerator = (int)((x - whole) * denominator); 

    if (numerator == 0) 
    { 
     return whole.ToString(); 
    } 
    while (numerator % 2 == 0) // simplify fraction 
    { 
     numerator /= 2; 
     denominator /=2; 
    } 
    return string.Format("{0} {1}/{2}", whole, numerator, denominator); 
} 

बोनस: कोड गोल्फ

public static string ToMixedFraction(decimal x) { 
    int w = (int)x, 
     n = (int)(x * 64) % 64, 
     a = n & -n; 
    return w + (n == 0 ? "" : " " + n/a + "/" + 64/a); 
} 
+0

ध्यान दें कि यहां तक ​​कि सत्ता के लिए विभाजक जाँच अनावश्यक है। मेरा जावा संस्करण देखें। – erickson

+0

egads, आप सही हैं :) – Jimmy

+0

अब देखो कि आपने मुझे क्या किया है ... एक बार जब आप कोड को ट्रिम करना शुरू कर देते हैं तो आप बस रुक सकते हैं। – Jimmy

0

मेरा कोड इस तरह दिखता है।

public static int gcd(int a, int b) 
    { 
     if (b == 0) 
      return a; 
     else 
      return gcd(b, a % b); 
    } 

public static String doubleToStringFraction(Double d) 
    { 
     StringBuffer result = new StringBuffer(" " + ((int) Math.floor(d))); 
     int whole = (int) ((d - Math.floor(d)) * 10000); 
     int gcd = gcd(whole, 10000); 
     result.append(" " + (whole/gcd) + "/" + 10000/gcd + " "); 
     return result.toString(); 
    } 
-1

इस समस्या को हल करने के लिए (अपनी परियोजनाओं में से एक में), मैं निम्नलिखित कदम उठाए:

  • दशमलव/अंश तार का एक शब्दकोश बनाया गया।
  • संख्या के "दशमलव" भाग और मिलान मानदंडों के आधार पर निकटतम मिलान करने वाले अंश के लिए शब्दकोश को खोजने के लिए एक फ़ंक्शन लिखा है।
4

org.apache.commons.math के बारे में कैसे? उनके पास एक फ्रैक्शन वर्ग है जो एक डबल लेता है।

http://commons.apache.org/math/api-1.2/org/apache/commons/math/fraction/Fraction.html

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

अंश बनाएं एक अंश डबल मूल्य और अधिकतम भाजक दिया (डबल मूल्य, maxDenominator int)।

+0

मैं इसे एक नज़र देता हूं, धन्यवाद। – Milhous

0

जैसा कि कई अन्य लोगों ने पीटा है, 64 के अंशों को आईईईई-फ्लोट द्वारा सटीक रूप से दर्शाया जा सकता है। इसका मतलब है कि हम बिट्स को घुमाने और मास्किंग करके एक अंश में भी परिवर्तित कर सकते हैं।

यह फ़्लोटिंग पॉइंट प्रस्तुतियों के सभी विवरणों को समझाने का स्थान नहीं है, कृपया विवरण के लिए wikipedia देखें।

संक्षेप में: एक फ़्लोटिंग पॉइंट नंबर (साइन) (एक्सपी) (फ्रैक) के रूप में संग्रहीत किया जाता है जहां साइन 1 बिट होता है, एक्सपी 11 बिट्स होता है और फ्रैक अंश भाग (1 के बाद) होता है और 52 बिट्स होता है। इस संख्या के रूप में enterpreted है:

(sign == 1 ? -1 : 1) * 1.(frac) * 2^(exp-1023) 

इस प्रकार, हम प्रतिपादक इंगित accoring चलती और बिंदु के बाद 6 बिट बाहर मास्किंग द्वारा 64 वें प्राप्त कर सकते हैं। जावा में:

private static final long MANTISSA_FRAC_BITMAP = 0xfffffffffffffl; 
private static final long MANTISSA_IMPLICIT_PREFIX = 0x10000000000000l; 
private static final long DENOM_BITMAP = 0x3f; // 1/64 
private static final long DENOM_LEN = 6; 
private static final int FRAC_LEN = 52; 

public String floatAsFrac64(double d) { 
    long bitmap = Double.doubleToLongBits(d); 
    long mantissa = bitmap & MANTISSA_FRAC_BITMAP | MANTISSA_IMPLICIT_PREFIX; 
    long exponent = ((bitmap >> FRAC_LEN) & 0x7ff) - 1023; 
    boolean negative = (bitmap & (1l << 63)) > 0; 

    // algorithm: 
    // d is stored as SE(11)F(52), implicit "1." before F 
    // move point to the right <exponent> bits to the right: 
    if(exponent > FRAC_LEN) System.out.println("warning: loosing precision, too high exponent"); 
    int pointPlace = FRAC_LEN-(int)exponent; 
    // get the whole part as the number left of the point: 
    long whole = mantissa >> pointPlace; 
    // get the frac part as the 6 first bits right of the point: 
    long frac = (mantissa >> (pointPlace-DENOM_LEN)) & DENOM_BITMAP; 
    // if the last operation shifted 1s out to the right, we lost precision, check with 
    // if any of these bits are set: 
    if((mantissa & ((MANTISSA_FRAC_BITMAP | MANTISSA_IMPLICIT_PREFIX) >> (pointPlace - DENOM_LEN))) > 0) { 
     System.out.println("warning: precision of input is smaller than 1/64"); 
    } 
    if(frac == 0) return String.format("%d", whole); 
    int denom = 64; 
    // test last bit, divide nom and demon by 1 if not 1 
    while((frac & 1) == 0) { 
     frac = frac >> 1; 
     denom = denom >> 1; 
    } 
    return String.format("%d %d/%d", whole, frac, denom); 
} 

(इस कोड को शायद इस तरह पर्याप्त यह है के रूप में मुश्किल है बिट flipping-कोड को पढ़ने में कम किया जा सकता है, लेकिन ...)

1

मैं अपने परियोजना मैं आशा के लिए यह लिखा यह उपयोगी हो सकता है:

//How to "Convert" double to fraction("a/b") - [email protected] 
private boolean isInt(double number){ 
    if(number%2==0 ||(number+1)%2==0){ 
     return true; 
    } 
    return false; 
} 
private String doubleToFraction(double doub){ 
    //we get the whole part 
    int whole = (int)doub; 
    //we get the rest 
    double rest = doub - (double)whole; 
    int numerator=1,denominator=1; 
    //if the whole part of the number is greater than 0 
    //we'll try to transform the rest of the number to an Integer 
    //by multiplying the number until it become an integer 
    if(whole >=1){ 
     for(int i = 2; ; i++){ 
      /*when we find the "Integer" number(it'll be the numerator) 
      * we also found the denominator(i,which is the number that transforms the number to integer) 
      * For example if we have the number = 2.5 when it is multiplied by 2 
      * now it's 5 and it's integer, now we have the numerator(the number (2.5)*i(2) = 5) 
      * and the denominator i = 2 
      */ 
      if(isInt(rest*(double)i)){ 
       numerator = (int)(rest*(double)i); 
       denominator = i; 
       break; 
      } 
      if(i>10000){ 
       //if i is greater than 10000 it's posible that the number is irrational 
       //and it can't be represented as a fractional number 
       return doub+""; 
      } 
     } 
     //if we have the number 3.5 the whole part is 3 then we have the rest represented in fraction 0.5 = 1/2 
     //so we have a mixed fraction 3+1/2 = 7/2 
     numerator = (whole*denominator)+numerator; 
    }else{ 
     //If not we'll try to transform the original number to an integer 
     //with the same process 
     for(int i = 2; ; i++){ 
      if(isInt(doub*(double)i)){ 
       numerator = (int)(doub*(double)i); 
       denominator = i; 
       break; 
      } 
      if(i>10000){ 
       return doub+""; 
      } 
     } 
    } 
    return numerator+"/"+denominator; 
} 
0

मैं बस फ्रैक्शन लाइब्रेरी बनाता हूं।

पुस्तकालय यहाँ उपलब्ध है: https://github.com/adamjak/Fractions

उदाहरण:

String s = "1.125"; 
Fraction f1 = Fraction.tryParse(s); 
f1.toString(); // return 9/8 

Double d = 2.58; 
Fraction f2 = Fraction.createFraction(d); 
f2.divide(f1).toString() // return 172/75 (2.29) 
संबंधित मुद्दे