2009-10-12 9 views
5

क्या frexp नामक सी/सी ++ फ़ंक्शन का जावा समतुल्य है? यदि आप परिचित नहीं हैं, तो frexp defined by Wikipedia है "मंथिसा और एक्सपोनेंट में फ़्लोटिंग-पॉइंट नंबर को तोड़ने के लिए।"क्या जावा का फ्रीएक्सपी बराबर है?

मैं गति और सटीकता दोनों के साथ कार्यान्वयन की तलाश में हूं, लेकिन अगर मैं केवल एक चुन सकता हूं तो मुझे सटीकता होगी।

यह पहले संदर्भ से कोड नमूना है। यह frexp अनुबंध थोड़ा और स्पष्ट करना चाहिए:

/* frexp example */ 
#include <stdio.h> 
#include <math.h> 

int main() 
{ 
    double param, result; 
    int n; 

    param = 8.0; 
    result = frexp (param , &n); 
    printf ("%lf * 2^%d = %f\n", result, n, param); 
    return 0; 
} 

/* Will produce: 0.500000 * 2^4 = 8.000000 */ 
+0

मैंने सोचा कि अपाचे कॉमन्स मैथ पैकेज यह ढूंढने के लिए एक अच्छी जगह हो सकता है, लेकिन मैंने वहां कुछ भी नहीं देखा। शायद आप इसके लिए एक फीचर अनुरोध डाल सकते हैं? या, यदि आप इसे स्वयं कोड करने का निर्णय लेते हैं, तो लाइब्रेरी में इसे शामिल करने के बारे में उनसे बात करें - मेरे लिए एक उपयोगी जोड़ जैसा लगता है। – Carl

+0

@ करल, मैं मानता हूं कि यह उपयोगी होगा। मैं खुद को और मेरा वर्कलोड बहुत अच्छी तरह से जानता हूं, इसलिए, मैं इसे स्वयं बनाने की कोशिश करने के लिए प्रतिबद्ध नहीं हूं। मुझे यकीन है कि मैं 80% काम 80% सही तरीके से कर सकता हूं, जब मुझे निवेश करना पड़ता है और यह बेकार से भी बदतर है .... –

+0

असली सवाल यह है: क्यों frexp टूट नहीं जाता है दो पूर्णांक में तैरें, लेकिन कम से कम एक फ्लोट चाहता है .. एक फ्लोट अपघटन के लिए जो समझ में नहीं आता है (लगता है कि रिकर्सन .....) –

उत्तर

3

इस कैसा है

।?
public static class FRexpResult 
{ 
    public int exponent = 0; 
    public double mantissa = 0.; 
} 

public static FRexpResult frexp(double value) 
{ 
    final FRexpResult result = new FRexpResult(); 
    long bits = Double.doubleToLongBits(value); 
    double realMant = 1.; 

    // Test for NaN, infinity, and zero. 
    if (Double.isNaN(value) || 
     value + value == value || 
     Double.isInfinite(value)) 
    { 
     result.exponent = 0; 
     result.mantissa = value; 
    } 
    else 
    { 

     boolean neg = (bits < 0); 
     int exponent = (int)((bits >> 52) & 0x7ffL); 
     long mantissa = bits & 0xfffffffffffffL; 

     if(exponent == 0) 
     { 
     exponent++; 
     } 
     else 
     { 
     mantissa = mantissa | (1L<<52); 
     } 

     // bias the exponent - actually biased by 1023. 
     // we are treating the mantissa as m.0 instead of 0.m 
     // so subtract another 52. 
     exponent -= 1075; 
     realMant = mantissa; 

     // normalize 
     while(realMant > 1.0) 
     { 
     mantissa >>= 1; 
     realMant /= 2.; 
     exponent++; 
     } 

     if(neg) 
     { 
     realMant = realMant * -1; 
     } 

     result.exponent = exponent; 
     result.mantissa = realMant; 
    } 
    return result; 
} 

यह "प्रेरित" या वास्तव में लगभग answer से समान सी # प्रश्न से समान रूप से कॉपी किया गया है। यह बिट्स के साथ काम करता है और फिर मंटिसा को 1.0 और 0.0 के बीच एक संख्या बनाता है।

+0

यिक्स! उपरोक्त कोड काफी सही नहीं है: यह (realMant> 1.0) के बजाय होना चाहिए (realMant> 1.0)। रिटर्न वैल्यू की परिमाण 1/2 (समावेशी) से 1 (अनन्य) की सीमा में होनी चाहिए, [जीएनयू libc मैनुअल] देखें (http://www.gnu.org/software/libc/manual/html_node/Normalization -Functions.html)। उपरोक्त कोड के साथ, frexp (1.0) गलती से 0.5 के बजाय 1.0 लौटाएगा। – akbertram

-1

मैं frexp समारोह से परिचित नहीं हूँ, लेकिन मैं आप BigDecimal 'में वृद्धि की और बगैर माप मूल्यों पर देखने की जरूरत है लगता है। 'unscaled' सटीक मंथिसा है, पैमाने एक्सपोनेंट है। Psuedocode में: value = unscaledValue 10^(- पैमाने)

1

Float.floatToIntBits और Double.doubleToLongBits देखें। आईईईई 754 फ्लोटिंग पॉइंट्स को डीकोड करने के लिए आपको अभी भी थोड़ा अतिरिक्त तर्क चाहिए।

+0

धन्यवाद - मुझे बिट्स पर जाने की क्षमता के बारे में पता है। जो मैं चिंतित हूं वह बिट सेट से पार्सिंग एस, ई, और एम का मूल मामला नहीं है।मैं frexp का पूर्ण कार्यान्वयन करने के बारे में अधिक चिंतित हूं जो सभी कोने मामलों (उदाहरण के लिए, नाएन के विभिन्न स्वाद) को संभालने के अनुबंध को बनाए रखता है। –

0

यह वही करता है जो आप चाहते हैं।

public class Test { 
    public class FRex { 

    public FRexPHolder frexp (double value) { 
     FRexPHolder ret = new FRexPHolder(); 

     ret.exponent = 0; 
     ret.mantissa = 0; 

     if (value == 0.0 || value == -0.0) { 
     return ret; 
     } 

     if (Double.isNaN(value)) { 
     ret.mantissa = Double.NaN; 
     ret.exponent = -1; 
     return ret; 
     } 

     if (Double.isInfinite(value)) { 
     ret.mantissa = value; 
     ret.exponent = -1; 
     return ret; 
     } 

     ret.mantissa = value; 
     ret.exponent = 0; 
     int sign = 1; 

     if (ret.mantissa < 0f) { 
     sign--; 
     ret.mantissa = -(ret.mantissa); 
     } 
     while (ret.mantissa < 0.5f) { 
     ret.mantissa *= 2.0f; 
     ret.exponent -= 1; 
     } 
     while (ret.mantissa >= 1.0f) { 
     ret.mantissa *= 0.5f; 
     ret.exponent++; 
     } 
     ret.mantissa *= sign; 
     return ret; 
    } 
    } 

    public class FRexPHolder { 
    int exponent; 
    double mantissa; 
    } 

    public static void main(String args[]) { 
    new Test(); 
    } 

    public Test() { 
    double value = 8.0; 
    //double value = 0.0; 
    //double value = -0.0; 
    //double value = Double.NaN; 
    //double value = Double.NEGATIVE_INFINITY; 
    //double value = Double.POSITIVE_INFINITY; 

    FRex test = new FRex(); 
    FRexPHolder frexp = test.frexp(value); 
    System.out.println("Mantissa: " + frexp.mantissa); 
    System.out.println("Exponent: " + frexp.exponent); 
    System.out.println("Original value was: " + value); 
    System.out.println(frexp.mantissa+" * 2^" + frexp.exponent + " = "); 
    System.out.println(frexp.mantissa*(1<<frexp.exponent)); 
    } 
} 
+0

@jitter, धन्यवाद लेकिन frexp वास्तव में गणितीय परिणाम को कम करने की कोशिश करने के बजाय आईईईई फ्लोटिंग पॉइंट मानक के बिट्स के साथ काम करता है। यह इस सवाल का लक्ष्य है। –

-1

नहीं वहाँ कोर जावा में या कॉमन्स लैंग में कोई वर्तमान कार्यान्वयन (यह पता लगाने के लिए सबसे अधिक संभावना अन्य जगह) में ठीक उसी कार्यक्षमता और frexp में आसानी होती है; मुझे पता है। यदि यह अस्तित्व में है तो यह शायद व्यापक रूप से उपयोग की जाने वाली टूलकिट में नहीं है।

0

मैं यह अधिकार पढ़ रहा हूँ तो ...

public class Frexp { 
    public static void main (String[] args) 
    { 
    double param, result; 
    int n; 

    param = 8.0; 
    n = Math.getExponent(param); 
    //result = ?? 

    System.out.printf ("%f * 2^%d = %f\n", result, n, param); 
    } 
} 

दुर्भाग्य से, वहाँ एक BigDecimal के लिए यह पहली बार परिवर्तित (या बस कर के बिना अपूर्णांश पाने के लिए निर्मित एक विधि के लिए प्रकट नहीं होता है विभाजन:। result = param/Math.pow(2,n)

अजीब पर्याप्त

, scalb ठीक विपरीत है: एक अपूर्णांश और प्रतिपादक लेते हैं और इसे से एक नई नाव उत्पन्न

+0

@ आर। व्यायाम का पूरा बिंदु कनवर्ट करना नहीं है। इसके बजाए, फ़ंक्शन आईईईई मानक फ्लोटिंग पॉइंट प्रस्तुति और डीकोड लेता है। लक्ष्य गणितीय अभिव्यक्ति के साथ नहीं आना है जो एक ही जवाब देने लगता है। –