programing

더블/플로트를 문자열로 변환

itmemos 2023. 10. 19. 22:02
반응형

더블/플로트를 문자열로 변환

부동 소수점 번호를 10진수(또는 기타 기본)의 동등한 문자열로 변환해야 합니다.변환은 처음에 형식으로 해야 합니다.xE+0어디에x는 부동 소수점 번호입니다.

제가 생각하는 것은 부동 소수점 숫자를 먼저 임시 정수로 잘라내고 그 정수를 문자열로 변환한 다음 분수 부분을 고려하여 곱하는 것입니다.10부분적인 부분은 다음과 같이 되지 않습니다.0 소수점 왼쪽으로 분수 부분이 옮겨진 후 정수를 문자열에 다시 적용하고 분수 부분을 문자열로 변환합니다.이것보다 더 빠른 방법이 있을까요?이 방법은 어떤 종류의 부작용을 유발할 수 있습니까?

부동 소수점을 지수로 변환하려면 위와 같이 한 후에 파워를 조절해야 합니까?또는 IEEE 754 부동 소수점 표현을 직접 비트 마스크하고 각 부분을 문자열로 변환합니다.

참고: 라이브러리 기능을 전혀 사용할 수 없기 때문에 다른 기능은 사용할 수 없습니다.이 코드는 장난감 알맹이에 들어갑니다.

사용하다snprintf()부터stdlib.h를 위해 나를 위해 일했습니다.

double num = 123412341234.123456789; 
char output[50];

snprintf(output, 50, "%f", num);

printf("%s", output);

정확한 값은 80비트의 경우 매우 수 있기 때문에 정확한 유일한 해결책은 기본 변환을 위해 임의 정밀 십진 산술을 수행하는 것입니다.long double, 소수점 이하 약 1만 자리까지.다행히 IEEE의 경우 약 700여 곳에 이릅니다.double.

개별 십진법 숫자로 작업하는 것보다 대신 10억 단위(32비트 정수에 맞는 10의 최고 거듭제곱)로 작업한 후 계산이 끝날 때마다 10억 단위의 숫자를 각각 9개씩의 십진법 숫자로 변환하는 것이 도움이 됩니다.

저는 매우 밀도가 높지만(읽는 것이 다소 어려운) 효율적인 구현을 여기서 수행하고 있습니다. LGPL MIT 라이선스:

http://git.musl-libc.org/cgit/musl/blob/src/stdio/vfprintf.c?h=v1.1.6

육각 플로트 서포트, 인피니티/난 서포트를 모두 떼어내면,%g/%f/%e변형 지원, 반올림(정확한 답변만 원한다면 절대 필요하지 않음), 기타 필요하지 않은 것들, 남은 코드는 다소 간단합니다.

가서 보세요.printf()로의 실행."%f"어떤 C도서관에서.

불필요할 수도 있지만 플로트를 문자열로 변환하는 기능을 만들었습니다.

코드:

#include <stdio.h>

/** Number on countu **/

int n_tu(int number, int count)
{
    int result = 1;
    while(count-- > 0)
        result *= number;

    return result;
}

/*** Convert float to string ***/
void float_to_string(float f, char r[])
{
    long long int length, length2, i, number, position, sign;
    float number2;

    sign = -1;   // -1 == positive number
    if (f < 0)
    {
        sign = '-';
        f *= -1;
    }

    number2 = f;
    number = f;
    length = 0;  // Size of decimal part
    length2 = 0; // Size of tenth

    /* Calculate length2 tenth part */
    while( (number2 - (float)number) != 0.0 && !((number2 - (float)number) < 0.0) )
    {
         number2 = f * (n_tu(10.0, length2 + 1));
         number = number2;

         length2++;
    }

    /* Calculate length decimal part */
    for (length = (f > 1) ? 0 : 1; f > 1; length++)
        f /= 10;

    position = length;
    length = length + 1 + length2;
    number = number2;
    if (sign == '-')
    {
        length++;
        position++;
    }

    for (i = length; i >= 0 ; i--)
    {
        if (i == (length))
            r[i] = '\0';
        else if(i == (position))
            r[i] = '.';
        else if(sign == '-' && i == 0)
            r[i] = '-';
        else
        {
            r[i] = (number % 10) + '0';
            number /=10;
        }
    }
}

에 BSDC 표준 라이브러리가 합니다.fcvt()할 수 있습니다 처음부터 코드를 작성하는 것보다 소스부터 시작할 수 있습니다. UNIX 98dfcvt()분명히 과학적 표기법을 출력하지 않기 때문에 당신이 직접 실행해야 할 것입니다. 하지만 저는 그것이 어려울 것이라고 생각하지 않습니다.

사용 방법:

void double_to_char(double f,char * buffer){
    gcvt(f,10,buffer);
}

또는 다음과 같은 C99 출력 형식을 사용할 수 있습니다.[-]0x1.<significand>p<biasied_exponent-bias>, 편견은0x3ff두 배의 정밀도의 숫자를 위해.또한 이 형식은 정확하고 부동 소수점 환경의 현재 설정(예: 반올림 또는 플러싱 데노멀을 0으로)에 의존하지 않으므로 직렬화할 때 선호되는 형식입니다.약간 일상적이지만 여전히 유용하고 매우 빠를 수도 있습니다.

당신의 질문을 "전환"으로 해석하겠습니다.double/float문자열"을 입력하고 제안된 형식을 너무 많이 입력하지 않습니다. "ASCII에서 가능한 한 좋은 값을 나타내는" 무언가를 원하시며 가급적이면 같은 부동 소수점 값으로 다시 라운드 트립할 수 있습니다.

다음과 같은 몇 가지 옵션이 있습니다.

  • Ryan Juckett은 이 4부작 블로그 포스트인 https://www.ryanjuckett.com/printing-floating-point-numbers 에서 자신의 (Dragon4) 구현을 꽤 잘 설명하고 있습니다.참고: 가 구현한 C++는 C++입니다. C가 사용 사례에 대한 엄격한 요구 사항이라면 이는 이야기의 대상이 아닙니다.
  • 로부터의netlib.org, 라이언의 블로그 게시물에서 언급된 내용:

    David Gay(위 논문 중 한 편의 저자)가 작성한 이 문서는 안전 구현이 인정된 것으로 보입니다.1991년부터 반복되어 파이썬에서 MySQL, 닌텐도 Wii에 이르기까지 모든 분야에서 사용되고 있습니다.

  • Ryan의 블로그 게시물에서도 언급되는 이중 변환 - Google V8 JS 엔진에서 사용 중인 구현.그리수2 알고리즘을 사용합니다.이는 다시 C++에 있으므로 옵션이 될 수도 있고 아닐 수도 있습니다.
  • 마일로 입(Milo Yip) RapidJ 구현SON. 이것은 몇몇 C++ 구조체를 사용하지만, 간단히 보면 이것이 필요하다면 아마도 꽤 쉽게 C로 변환될 수 있음을 알 수 있습니다.

1: https://kurtstephens.com/files/p372-steele.pdf

2:https://www.cs.tufts.edu/ ~nr/cs257/ archive/ flor-loitsch/printf.pdf

sprintf는 다음을 수행할 수 있습니다.

#include <stdio.h>
int main() {
  float w = 234.567;
  char x[__SIZEOF_FLOAT__];
  sprintf(x, "%g", w);
  puts(x);
}

언급URL : https://stackoverflow.com/questions/7228438/convert-double-float-to-string

반응형