2010-01-03 14 views
8

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

उत्तर

3

ले लो कुछ ज्ञात कार्यान्वयन (कि atof पर निर्भर नहीं करता है), जैसे गहरे लाल रंग का साथ वितरित एक के रूप में: ruby_1_8/missing/strtod.c

+0

धन्यवाद। यही वही है जो मैं खोज रहा हूं। एक अच्छी तरह से परीक्षण और स्वच्छ कार्यान्वयन। – bert

+0

मुझे डर है कि यह सही कार्यान्वयन नहीं है, इसे गोल करने की परवाह नहीं है, जो स्ट्रिंग-डबल कनवर्टिंग में एक बहुत ही महत्वपूर्ण बात है। कृपया "फ़्लोटिंग-पॉइंट रूपांतरण के लिए सही ढंग से बढ़ाए गए दशमलव" पर Google देखें और एक नज़र डालें। – amanjiang

0

वहाँ भी है netlib पर gdtoa उपलब्ध, बीएसडी शैली लाइसेंस: http://www.netlib.org/fp/gdtoa.tgz

+0

gdtoa डबल से स्ट्रिंग को परिवर्तित करता है जबकि ओपी डबल रूपांतरण के लिए स्ट्रिंग की तलाश में है। – vitaut

+0

@ विटॉट में इसमें दोनों चीजों के कार्यान्वयन हैं, यह सिर्फ 'dtoa() ' – Spudd86

2

ऊपर जवाब के बाद, मैं ruby_1_8/missing/strtod.c पर रूबी कार्यान्वयन उपयोग करने की कोशिश।

char * endptr ; 
double value1 = 1.15507e-173 ; 
double value2 = strtod("1.15507e-173", &endptr) ; 
double value3 = test_strtod("1.15507e-173", &endptr) ; 
assert(sizeof(double) == sizeof(unsigned long)) ; 
printf("value1 = %lg, 0x%lx.\n", value1, *(unsigned long*)(&value1)) ; 
printf("value2 = %lg, 0x%lx.\n", value2, *(unsigned long*)(&value2)) ; 
printf("value3 = %lg, 0x%lx.\n", value2, *(unsigned long*)(&value3)) ; 
assert(value1 == value2) ; 
assert(value1 == value3) ; 

जो प्रिंट

value1 = 1.15507e-173, 0x1c06dace8bda0ee0. 
value2 = 1.15507e-173, 0x1c06dace8bda0ee0. 
value3 = 1.15507e-173, 0x1c06dace8bda0edf. 
Assertion failed: (value1 == value3), function main, file main.c, line 16. 

तो मेरी सलाह: हालांकि, कुछ इनपुट के लिए यह जीसीसी के पार्सर में निर्मित और stdlib.h से strtod करने के लिए अलग अलग जवाब, मैक पर और Linux प्लेटफार्मों पर दोनों देता है उपयोग से पहले चुने गए कार्यान्वयन का परीक्षण करना है।

2

चेतावनी: रूबी से प्रस्तावित कार्यान्वयन में बग शामिल हैं। मैं छोटा सा फर्क गेविन द्वारा बताया मन नहीं होता, लेकिन अगर आप की तरह कुछ पार्स करने के लिए कोशिश "0,000000000000000000000000000000000000783475" आप 7.834750e-37 के बजाय 0.0 मिल जाएगा (शेयर strtod की तरह() लौट जाता है।)

अन्य समाधान:

#include <sstream> 
#include "strtod_locale_independent.h" 

extern "C" double strtod_locale_independent(const char* s) 
{ 
    std::istringstream text(s); 
    text.imbue(std::locale::classic()); 
    double result; 
    text >> result; 
    return result; 
} 

मुझे नहीं पता कि यह कितना तेज़ है।

+0

का कार्यान्वयन नहीं है, यह बिल्टिन स्ट्रेट की तुलना में लगभग 5x धीमी है, और आपको अंत सूचक नहीं देता है, जिसकी आवश्यकता होती है जब आप' पार्सिंग के लिए इसका इस्तेमाल कर रहे हैं। –

+0

हाँ आप सही हैं। लेकिन बिंदु प्रदर्शन नहीं है। यह लोकेल निर्भरता है। इसलिए, 'strtod() 'का उपयोग नहीं किया जा सकता है। –

+2

बिंदु यह है कि यह स्ट्रेट के लिए एक प्रतिस्थापन नहीं है। –

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