2010-01-03 9 views
8

필자는 항상 '.'점을 사용하는 두 개의 숫자를 구문 분석해야하는 라이브러리가 있습니다. 소수점 구분 기호로 사용됩니다. 불행히도이 경우 strtod()는 다른 구분 기호를 사용할 수있는 로캘을 고려하므로 구문 분석이 실패 할 수 있습니다. 난 setlocale() 할 수 없다 - 스레드로부터 안전하지 않다. 그래서 지금은 깨끗한 로케일 독립적 인 strtod 구현을 찾고 있습니다. 지금까지 여러 구현을 찾았지만 모두 해커처럼 보이거나 나쁜 코드처럼 보입니다. 누군가 나를 잘 테스트하고 작동하며 깨끗한 (ANSI) C 구현을 권장 할 수 있습니까?로케일 독립적 인 strtod 구현

답변

3

ruby ​​: ruby_1_8/missing/strtod.c과 함께 배포되는 것과 같이 알려진 구현 (atof에 종속되지 않음)을 가져옵니다.

+0

감사합니다. 그게 내가 찾고 있었던 바로 그 것이다. 잘 테스트되고 깨끗한 구현. – bert

+0

이것은 올바른 구현이 아닌가 걱정됩니다. 문자열 이중 변환에서 매우 중요한 반올림은 신경 쓰지 않았습니다. google "소수점을 반올림하여 부동 소수점으로 올바르게 반올림"하고보십시오. – amanjiang

0

가이기도 NETLIB에 gdtoa 가능, BSD 스타일의 라이센스 : http://www.netlib.org/fp/gdtoa.tgz

+0

gdtoa는 double을 string으로 변환하고 OP는 double to string 변환을 찾습니다. – vitaut

+0

@vitaut 그것은 두 가지 구현을 모두 가지고있다. 단지'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. 

그래서 내 조언을 인쇄 : 그러나 일부 입력이 맥에 리눅스 플랫폼에서 모두 GCC의 파서 내장 및 stdlib.h에서의 strtod하는 서로 다른 답변을 제공합니다 사용하기 전에 선택한 구현을 테스트하는 것입니다.

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

이것은 내장 strtod보다 약 5 배 느리고, 끝 포인터를주지 않는다. 다시 파싱에 사용합니다. –

+0

예, 맞습니다. 그러나 요점은 성과가 아닙니다. 로켈 종속성입니다. 따라서'strtod()'는 사용할 수 없습니다. –

+2

요점은 이것이 strtod를 대체하지 않는다는 것입니다. –

관련 문제