2009-04-09 9 views
5

मैं 0 डी -8 कहता हूं कि कुछ डेल्टा द्वारा "समान मूल्य" के लंबे समय तक विचलित होने वाले 0 डी ऊपर से पहला डबल जानना चाहता हूं, 1e-8 कहें। मैं यद्यपि यहां असफल रहा हूँ। मैं इसे सी में करने की कोशिश कर रहा हूं हालांकि मैं आमतौर पर प्रबंधित भाषाओं का उपयोग करता हूं, बस मामले में। कृपया मदद करे। मैं पसंद करते हैं मज़ा सी -डेल्टा द्वारा अपने लंबे समय से विचलित होने वाला पहला डबल क्या है?


#include <stdio.h> 
#include <limits.h> 
#define DELTA 1e-8 

int main() { 
    double d = 0; // checked, the literal is fine 
    long i; 
    for (i = 0L; i < LONG_MAX; i++) { 
     d=i; // gcc does the cast right, i checked 
     if (d-i > DELTA || d-i < -DELTA) { 
       printf("%f", d); 
       break; 
     } 
    } 
}

मेरा अनुमान है कि मुद्दा यह है कि di मैं दोगुना है और इसलिए करने के लिए घ == मैं और फिर अंतर हमेशा 0. है और कैसे मैं पता लगा सकते हैं यह ठीक से डाले है कि स्ट्रिंग की तुलना करने पर कास्टिंग, जो हमेशा के लिए ले जाएगा।

ANSWER: जैसा कि हम उम्मीद करते हैं। मानक सी/यूनिक्स/पॉज़िक्स उपकरण के अनुसार 2^53 + 1 = 9007199254740993 अंतर का पहला बिंदु है। अपने कार्यक्रम के लिए पैक्स के लिए बहुत बहुत धन्यवाद। और मुझे लगता है कि गणित फिर से जीतता है।

+2

उपरोक्त कोड प्रत्येक पूर्णांक के माध्यम से व्यापक हो रहा है। मैं इसके बजाए एक बाइनरी खोज पर विचार करूंगा। इसे 2^53 के बजाय 53 या तो पुनरावृत्तियों के साथ अभिसरण करना चाहिए। –

+0

प्रतिनिधित्व के कुछ पूर्व ज्ञान के बिना बाइनरी खोज काम नहीं करेगा। ** सभी की ** ** शक्तियां बिल्कुल दोगुनी हैं, इसलिए यदि आपकी द्विआधारी खोज दो की शक्तियों को चलने के लिए होती है, तो यह वांछित बिंदु को पूरी तरह से याद कर सकता है ... :-) –

+2

संभावित डुप्लिकेट [जो पहला पूर्णांक है कि एक आईईईई 754 फ्लोट बिल्कुल प्रतिनिधित्व करने में असमर्थ है?] (http://stackoverflow.com/questions/3793838/which-is-the-first-integer-that-an-ieee-754-float-is-incapable-of -representing-e) –

उत्तर

12

आईईई 754 में डबल्स में 52 बिट्स की सटीकता है जिसका अर्थ है कि वे संख्याओं को कम से कम (0 कम से कम) 2 तक स्टोर कर सकते हैं।

यदि आपकी लम्बाई 32-बिट है, तो उनके पास केवल (सकारात्मक) रेंज 0 से 2 होगी, इसलिए 32-बिट लंबा नहीं है जिसे बिल्कुल डबल के रूप में प्रदर्शित नहीं किया जा सकता है। 64-बिट लंबे के लिए, यह (लगभग) 2 होगा, इसलिए मैं शून्य पर नहीं, वहां चारों ओर शुरू कर रहा हूं।

आप निम्न प्रोग्राम का उपयोग यह पता लगाने के लिए कर सकते हैं कि विफलता कहां शुरू होती है। एक पूर्व संस्करण मैंने इस तथ्य पर भरोसा किया था कि एक संख्या में अंतिम अंक जो लगातार युगल होता है अनुक्रम {2,4,8,6} का पालन करता है। हालांकि, मैंने आखिरकार अंतिम अंक की जांच करने के लिए अंततः एक ज्ञात विश्वसनीय उपकरण (bc) का उपयोग करने का विकल्प चुना।

ध्यान रखें कि इस युगल की असली सटीकता sprintf() की कार्रवाई के बजाय से प्रभावित हो सकता (मैं तो व्यक्तिगत रूप से, क्योंकि यह 2 अप करने के लिए निश्चित संख्या के साथ कोई मुसीबतों था नहीं लगता कि)।

2^51 - 1 = 2251799813685247 
2^52 - 1 = 4503599627370495 
2^53 - 1 = 9007199254740991 
2^54 - 1 <-- bc failure 
    got  [18014398509481984] 
    expected [18014398509481983] 

जहां मैं इसे विफल करने की उम्मीद के बारे में है जो:

#include <stdio.h> 
#include <string.h> 

int main() { 
    FILE *fin; 
    double d = 1.0; // 2^n-1 to avoid exact powers of 2. 
    int i = 1; 
    char ds[1000]; 
    char tst[1000]; 

    // Loop forever, rely on break to finish. 
    while (1) { 
     // Get C version of the double. 
     sprintf (ds, "%.0f", d); 

     // Get bc version of the double. 
     sprintf (tst, "echo '2^%d - 1' | bc >tmpfile", i); 
     system(tst); 
     fin = fopen ("tmpfile", "r"); 
     fgets (tst, sizeof (tst), fin); 
     fclose (fin); 
     tst[strlen (tst) - 1] = '\0'; 

     // Check them. 
     if (strcmp (ds, tst) != 0) { 
      printf("2^%d - 1 <-- bc failure\n", i); 
      printf(" got  [%s]\n", ds); 
      printf(" expected [%s]\n", tst); 
      break; 
     } 

     // Output for status then move to next. 
     printf("2^%d - 1 = %s\n", i, ds); 
     d = (d + 1) * 2 - 1; // Again, 2^n - 1. 
     i++; 
    } 
} 

यह जब तक चलती है:

इस कार्यक्रम है।

एक के रूप में अलग रूप में, मैं मूल रूप से संख्या प्रपत्र 2 n का इस्तेमाल किया लेकिन यह है कि अप करने के लिए मुझे मिल गया: एक डबल 8 बाइट्स होने का आकार (sizeof के साथ की जाँच) के साथ

2^136 = 87112285931760246646623899502532662132736 
2^137 = 174224571863520493293247799005065324265472 
2^138 = 348449143727040986586495598010130648530944 
2^139 = 696898287454081973172991196020261297061888 
2^140 = 1393796574908163946345982392040522594123776 
2^141 = 2787593149816327892691964784081045188247552 
2^142 = 5575186299632655785383929568162090376495104 
2^143 <-- bc failure 
    got  [11150372599265311570767859136324180752990210] 
    expected [11150372599265311570767859136324180752990208] 

। यह पता चला कि ये संख्या द्विआधारी रूप "1000..." थीं जिन्हें अब तक डबल्स के साथ प्रदर्शित किया जा सकता है। यह तब होता है जब मैंने बेहतर बिट पैटर्न प्राप्त करने के लिए 2 n -1 का उपयोग करने के लिए स्विच किया: सभी एक बिट्स।

+0

संक्षिप्त, और आपने यह भी पता लगाया कि मेरा कार्यक्रम संभवतः क्यों काम नहीं करेगा। न केवल कास्टिंग, बल्कि यह तथ्य कि लंबे समय तक केवल 32-बिट है। शायद सी वास्तव में पत्थर की उम्र है, और मैं वापस नहीं जा रहा हूँ। – Overflown

+0

इस समस्या को जोड़ने के लिए बहुत बहुत धन्यवाद। मैंने सोचा कि आपको तारों का उपयोग करना है, आप जिस काम के साथ काम कर रहे हैं उससे अधिक परिशुद्धता पर परीक्षण करने का कोई और तरीका नहीं है। – Overflown

+0

मुझे दो^53 + 1 (9007199254740993) मिलाकर एक डबल के रूप में कास्ट किया गया, जिसके परिणामस्वरूप लंबे समय तक कास्ट किया गया। 9001299254740992 – karmakaze

0

हाथ से, मैंने सोचा कि युगल सभी पूर्णांक (उनकी सीमाओं के भीतर) का प्रतिनिधित्व कर सकता है।

अगर ऐसा नहीं है, तो आप उनमें से या तो से अधिक परिशुद्धता के साथ कुछ करने के लिए दोनों मैं और डी कास्ट करना चाहते हैं जा रहे हैं। शायद एक लंबा डबल काम करेगा।

+0

मुझे लगता है कि आपका मतलब है "int के रूप में प्रतिनिधित्व करने वाले पूर्णांक" वास्तव में युगल के रूप में प्रतिनिधित्व योग्य होंगे। यह सच है जब दो में मंटिसा अंकों की संख्या int में अंकों की संख्या से अधिक है। यह याद रखने योग्य है कि उच्च एक्सपोनेंट मानों पर, प्रतिनिधित्व करने योग्य फ़्लोटिंग पॉइंट संख्याओं के बीच की दूरी 1 से अधिक हो सकती है, ताकि सभी पूर्णांक फ़्लोटिंग पॉइंट में बिल्कुल प्रतिनिधित्व न हों। –

2

डबल पर डालने पर 'गलत' होने वाला पहला लंबा 1e-8 से बंद नहीं होगा, यह 1 तक बंद हो जाएगा। जब तक डबल इसके महत्व में लंबे समय तक फिट हो सकता है, तो यह इसका प्रतिनिधित्व करेगा सही रूप में।

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

विकिपीडिया significand में 52 बिट, अंतर्निहित प्रारंभिक 1. 2^53 की गिनती नहीं है कि पहली लंबी मतलब यह होना चाहिए एक अलग मान पर डाली जा करने के लिए कर रहा है कहते हैं।

+0

मुझे विकिपीडिया से गणित विचार पसंद है, मैं सिर्फ सबूत का उपयोग करने की कोशिश कर रहा था। – Overflown

1

हालांकि मैं इस चर्चा में फोरट्रान 95 और उत्तराधिकारी का उल्लेख करने में संकोच कर रहा हूं, लेकिन मैं उल्लेख करूंगा कि 1 99 0 के मानक के बाद से फोरट्रान ने एक स्पैनिशिंग आंतरिक कार्य की पेशकश की है जो आपको बताती है कि प्रतिनिधित्व योग्य वास्तविकताओं के बीच का अंतर किसी दिए गए वास्तविक के बारे में क्या है। आप इस पर बाइनरी खोज कर सकते हैं, जब स्पेसिंग (एक्स)> DELTA रोकना। उन कंपाइलरों के लिए जो एक ही फ़्लोटिंग पॉइंट मॉडल का उपयोग करते हैं, जिसकी आप रुचि रखते हैं (संभवतः आईईईई 754 मानक होने की संभावना है), आपको वही परिणाम मिलना चाहिए।

+0

सी ++ 11 में और बाद में हमारे पास 'डबल स्टडी :: अगला (डबल एक्स, लम्बी डबल वाई) '' y' की दिशा में 'x' के बाद अगले प्रतिनिधित्व योग्य संख्या के लिए। इसके अलावा, दूसरे तर्क में कम परिशुद्धता में: 'इसके बाद डबल (डबल एक्स, डबल वाई); '। हालांकि यह अंतर के समान नहीं है। – emsr

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