Programowanie w języku C/C++

Konwersje liczb

  • 2 komentarze
  • 4456 odsłon
  • Oceń ten tekst jako pierwszy
Na forum jest wiele pytań o konwersje liczb całkowitych i zmienno-przecinkowych do string'ów i na odwrót, najczęstszą odpowiedzią jest użycie funkcji sprintf lecz jest to metoda dość wolna i obchodzi rzeczywisty problem, poniżej jest fragment kodu szerszej biblioteki do obslugi ciągów znaków, który umożliwia konwersje int,float <-> string, kod jest zgodny ze standardem C99, jest tu umieszczony wyłącznie jako przykład. Kod umożliwia także operacje na typach long long (int64_t) oraz long double.

Pełny kod biblioteki (nadal w trakcje rozwoju) pod adresem http://cepa.one.pl/libstr.


We wszystkich funkcjach parametr @base oznacza podstawe systemu liczbowego.

inline int libstr_isbdigit(int c, int base);

Sprawdza czy dany znak należy do systemu liczbowego.

uint32_t libstr_atoul(const char *a, int base);

Konwersja string -> unsigned long.

int32_t libstr_atol(const char *a, int base);

Konwersja string -> long.

uint64_t libstr_atoull(const char *a, int base);

Konwersja string -> unsigned long long.

int64_t libstr_atoll(const char *a, int base);

Konwersja string -> long long.


W poniższych funkcjach wskaznik @a jest wskaznikiem do bufora o wystarczającej dlugosci, w przypadku int32_t jest to 33 bajtów, przy int64_t jest to 65 bajtów.

char *libstr_ultoa(uint32_t x, int base, char *a);

Konwersja unsigned long -> string.

char *libstr_ltoa(int32_t x, int base, char *a);

Konwersja long -> string.

char *libstr_ulltoa(uint64_t x, int base, char *a);

Konwersja unsigned long long -> string.

char *libstr_lltoa(int64_t x, int base, char *a);

Konwersja long long -> string.


double libstr_atod(const char *a);

Konwersja string -> double.

long double libstr_atold(const char *a);

Konwersja string -> long double.


Poniższe funkcje konwertują liczbe zmienno-przecinkową na ciąg cyfr bez kropki dziesiętnej i wykładnika. Są bazą dla właściwych funkcji które wstawiają kropkę, wykładnik znak itd.
Opis:

  • ecvt - Zwraca reprezentacje liczby, tak aby było dokładnie @nDigits wszystkich cyfr, jeżeli wymaga to zaokrąglenia to liczba jest zaokrąglana w góre.
  • fcvt - Zwraca reprezentacje liczby, tak aby bylo dokładnie @nDigits cyfr po kropce dziesiętnej, jeżeli wymaga to zaokrąglenia to liczba jest zaokrąglana w górę.

Parametry:
@flt - liczba
@nDigits - liczba cyfr (ecvt: wszystkich, fcvt: po przecinku)
@decPoint - pozycja kropki dziesiętnej
@sign - jezeli 0 to + jak 1 to -
@a - bufor


char *libstr_ecvtbuf(double flt, int nDigits, int *decPoint, int *sign, char *a);

Konwersja double -> string. Używana do konwersji do notacji naukowej.

char *libstr_fcvtbuf(double flt, int nDigits, int *decPoint, int *sign, char *a);

Konwersja double -> string. Używana do konwersji do notacji dziesiętnej.

char *libstr_lecvtbuf(long double flt, int nDigits, int *decPoint, int *sign, char *a);

Konwersja long double -> string. Używana do konwersji do notacji naukowej.

char *libstr_lfcvtbuf(long double flt, int nDigits, int *decPoint, int *sign, char *a);

Konwersja long double -> string. Używana do konwersji do notacji dziesiętnej.


Właściwe konwersje.
/**
 * Enhanced String Library
 * Copyright (c) 2005-2007 Lukasz Cepowski (cepa[at]o2.pl)
 * GNU GPL
 * http://cepa.one.pl/libstr
 */
 
/*$ libstr_conv.c 2000 2007-03-26 $*/
 
#include <libstr.h>
#include "libstr_internal.h"
#include <math.h>
#include <float.h>
 
/**
 * libstr_isbdigit - Return digit value in given numerical system if character
 * is a digit from given numerical system, otherwise -1.
 */
inline int libstr_isbdigit(int c, int base)
{
        c = (unsigned char)c;
        if (c >= '0' && c <= '9') {
                c -= '0';
                if (c < base) return c;
        } else if (c >= 'a' && c <= 'z') {
                c -= 'a';
                base -= 10;
                if (c < base) return c + 10;
        } else if (c >= 'A' && c <= 'Z') {
                c -= 'A';
                base -= 10;
                if (c < base) return c + 10;
        }
        return -1; /* is not */
}
 
/**
 * libstr_atoul - Convert string to the unsinged 32bit integer value.
 * @base - numerical system (2..36),
 * Function returns numbers between 0 and UINT32_MAX.
 */
uint32_t libstr_atoul(const char *a, int base)
{
        uint32_t result = 0;
        int digit = 0;
 
        assert(a);
 
        /* skip whitespaces */
        while (isspace(*a)) a++;
 
        while (*a) {
                if ((digit = libstr_isbdigit(*a, base)) == -1) break;
                result *= base;
                result += digit;
                a++;
        }
        return result;
}
 
/**
 * libstr_atol - Convert string to the signed 32bit integer value.
 * @base - numerical system (2..36),
 * Function returns numbers between INT32_MIN and INT32_MAX.
 */
int32_t libstr_atol(const char *a, int base)
{
        int32_t result = 0;
        int digit = 0, isNegative = 0;
 
        assert(a);
 
        /* skip whitespaces */
        while (isspace(*a)) a++;
 
        if (*a == '-') {
                a++;
                isNegative = 1;
        }
        while (*a) {
                if ((digit = libstr_isbdigit(*a, base)) == -1) break;
                result *= base;
                result += digit;
                a++;
        }
        if (isNegative) return -result;
        return result;
}
 
/**
 * libstr_atoull - Convert string to the unsinged 64bit integer value.
 * @base - numerical system (2..36),
 * Function returns numbers between 0 and UINT64_MAX.
 */
uint64_t libstr_atoull(const char *a, int base)
{
        uint64_t result = 0;
        int digit = 0;
 
        assert(a);
 
        /* skip whitespaces */
        while (isspace(*a)) a++;
 
        while (*a) {
                if ((digit = libstr_isbdigit(*a, base)) == -1) break;
                result *= base;
                result += digit;
                a++;
        }
        return result;
}
 
/**
 * libstr_atoll - Convert string to the signed 64bit integer value.
 * @base - numerical system (2..36),
 * Function returns numbers between INT64_MIN and INT64_MAX.
 */
int64_t libstr_atoll(const char *a, int base)
{
        int64_t result = 0;
        int digit = 0, isNegative = 0;
 
        assert(a);
 
        /* skip whitespaces */
        while (isspace(*a)) a++;
 
        if (*a == '-') {
                a++;
                isNegative = 1;
        }
        while (*a) {
                if ((digit = libstr_isbdigit(*a, base)) == -1) break;
                result *= base;
                result += digit;
                a++;
        }
        if (isNegative) return -result;
        return result;
}
 
/**
 * libstr_ultoa - Convert unsigned 32bit integer in given numerical system to the
 * string.
 * @base - numerical system (2..36),
 * @a - pointer to the buffer, minimum size is 33bytes,
 * Return pointer to the string (a) or NULL.
 */
char *libstr_ultoa(uint32_t x, int base, char *a)
{
        int digStack[32], n = 0, m = 0;
        uint32_t y = 0;
 
        assert(a);
 
        if (x == 0) {
                a[0] = '0';
                a[1] = '\0';
                return a;
        }
 
        while (x != 0) {
                y = x;
                x /= base;
                digStack[n++] = (int)(y - x * base);
        }
 
        while (n--) {
                a[m++] = (digStack[n] < 10 ? digStack[n] + '0' : digStack[n] - 10 + 'a');
        }
 
        a[m] = '\0';
 
        return a;
}
 
/**
 * libstr_ltoa - Convert signed 32bit integer in given numerical system to the
 * string.
 * @base - numerical system (2..36),
 * @a - pointer to the buffer, minimum size is 33bytes,
 * Return pointer to the string (a) or NULL.
 */
char *libstr_ltoa(int32_t x, int base, char *a)
{
        int digStack[32], n = 0, m = 0;
        int32_t y = 0;
 
        assert(a);
 
        if (x == 0) {
                a[0] = '0';
                a[1] = '\0';
                return a;
        } else if (x < 0) {
                a[0] = '-';
                m = 1;
        }
 
        if (x < 0) while (x != 0) {
                y = x;
                x /= base;
                digStack[n++] = -(int)(y - x * base);
        } else while (x != 0) {
                y = x;
                x /= base;
                digStack[n++] = (int)(y - x * base);
        }
 
        while (n--) {
                a[m++] = (digStack[n] < 10 ? digStack[n] + '0' : digStack[n] - 10 + 'a');
        }
 
        a[m] = '\0';
 
        return a;
}
 
/**
 * libstr_ulltoa - Convert unsigned 64bit integer in given numerical system to the
 * string.
 * @base - numerical system (2..36),
 * @a - pointer to the buffer, minimum size is 65bytes,
 * Return pointer to the string (a) or NULL.
 */
char *libstr_ulltoa(uint64_t x, int base, char *a)
{
        int digStack[64], n = 0, m = 0;
        uint64_t y = 0;
 
        assert(a);
 
        if (x == 0) {
                a[0] = '0';
                a[1] = '\0';
                return a;
        }
 
        while (x != 0) {
                y = x;
                x /= base;
                digStack[n++] = (int)(y - x * base);
        }
 
        while (n--) {
                a[m++] = (digStack[n] < 10 ? digStack[n] + '0' : digStack[n] - 10 + 'a');
        }
 
        a[m] = '\0';
 
        return a;
}
 
/**
 * libstr_lltoa - Convert signed 64bit integer in given numerical system to the
 * string.
 * @base - numerical system (2..36),
 * @a - pointer to the buffer, minimum size is 65bytes,
 * Return pointer to the string (a) or NULL.
 */
char *libstr_lltoa(int64_t x, int base, char *a)
{
        int digStack[64], n = 0, m = 0;
        int64_t y = 0;
 
        assert(a);
 
        if (x == 0) {
                a[0] = '0';
                a[1] = '\0';
                return a;
        } else if (x < 0) {
                a[0] = '-';
                m = 1;
        }
 
        if (x < 0) while (x != 0) {
                y = x;
                x /= base;
                digStack[n++] = -(int)(y - x * base);
        } else while (x != 0) {
                y = x;
                x /= base;
                digStack[n++] = (int)(y - x * base);
        }
 
        while (n--) {
                a[m++] = (digStack[n] < 10 ? digStack[n] + '0' : digStack[n] - 10 + 'a');
        }
 
        a[m] = '\0';
 
        return a;
}
 
/**
 * libstr_atod - Convert string to the double.
 */
double libstr_atod(const char *a)
{
        double result = 0.0f, sign = 1.0f;
        int digit = 0, coma = 0, exp = 0, neg = 1;
 
        assert(a);
 
        /* skip whitespaces */
        while (isspace(*a)) a++;
 
        /* get sign */
        switch (*a) {
                case '-': sign = -1.0f;
                case '+': a++;
        }
 
        /* parse base */
        while ((digit = libstr_isbdigit(*a, 10)) != -1) {
                result *= 10.0f;
                result += (double)digit;
                a++;
        }
 
        /* parse fraction */
        if (*a == '.') {
                a++;
                while ((digit = libstr_isbdigit(*a, 10)) != -1) {
                        result *= 10.0f;
                        result += (double)digit;
                        a++;
                        coma++;
                }
        }
 
        /* parse exponent */
        if (*a == 'e' || *a == 'E') {
                a++;
                switch (*a) {
                        case '-': neg = -1;
                        case '+': a++;
                }
                while ((digit = libstr_isbdigit(*a, 10)) != -1) {
                        exp *= 10;
                        exp += digit;
                        a++;
                }
        }
 
        exp *= neg;
        exp -= coma;
 
        if (exp > 0) {
                while (exp--)
                        result *= 10.0f;
        } else if (exp < 0) {
                while (exp++)
                        result /= 10.0f;
        }
 
        return sign * result;
}
 
/**
 * libstr_atold - Convert string to the long double.
 */
long double libstr_atold(const char *a)
{
        long double result = 0.0f, sign = 1.0f;
        int digit = 0, coma = 0, exp = 0, neg = 1;
 
        assert(a);
 
        /* skip whitespaces */
        while (isspace(*a)) a++;
 
        /* get sign */
        switch (*a) {
                case '-': sign = -1.0f;
                case '+': a++;
        }
 
        /* parse base */
        while ((digit = libstr_isbdigit(*a, 10)) != -1) {
                result *= 10.0f;
                result += (long double)digit;
                a++;
        }
 
        /* parse fraction */
        if (*a == '.') {
                a++;
                while ((digit = libstr_isbdigit(*a, 10)) != -1) {
                        result *= 10.0f;
                        result += (long double)digit;
                        a++;
                        coma++;
                }
        }
 
        /* parse exponent */
        if (*a == 'e' || *a == 'E') {
                a++;
                switch (*a) {
                        case '-': neg = -1;
                        case '+': a++;
                }
                while ((digit = libstr_isbdigit(*a, 10)) != -1) {
                        exp *= 10;
                        exp += digit;
                        a++;
                }
        }
 
        exp *= neg;
        exp -= coma;
 
        if (exp > 0) {
                while (exp--)
                        result *= 10.0f;
        } else if (exp < 0) {
                while (exp++)
                        result /= 10.0f;
        }
 
        return sign * result;
}
 
static int cvt_round_up(char *a, int nDigits)
{
        int rest = 1, i = 0;
 
        i = nDigits;
        while (i--) {
                a[i] += rest;
                rest = 0;
                if (a[i] > '9') {
                        a[i] = '0';
                        rest = 1;
                }
        }
 
        if (rest != 0) {
                a[0] = '1';
                a[nDigits] = '0';
                a[nDigits+1] = '\0';
        }
 
        return rest;
}
 
/**
 * libstr_ecvtbuf - Convert double to string.
 * @x - double float variable,
 * @nDigits - count of returned digits,
 * @decPoint - pointer to variable with position of decimal point,
 * @sign - pointer to variable with sign (+ => 0, - => 1),
 * @a - buffer,
 *
 * Size of the buffer should be enough to store all bytes from conversion.
 * The value of double is between 2,2E-308 and 1,8E+308 so
 * DBL_MAX_10_EXP + 2 bytes are enough.
 * Sometimes value is rouned up if given n-digits variable is less than
 * nominal size of converted string.
 * Function returns a pointer to the @a, count of used bytes is always equal
 * to @nDigits.
 */
char *libstr_ecvtbuf(double flt, int nDigits, int *decPoint, int *sign, char *a)
{
        int exp = 0, digit = 0, i = 0;
 
        assert(a);
        assert(nDigits <= DBL_MAX_10_EXP); /* 308 */
 
        /* get sign */
        if (flt < 0.0f && sign) *sign = 1;
        else if (sign) *sign = 0;
 
        /* abs */
        flt = fabs(flt);
 
        /* get exponent */
        exp = (int)log10(flt);
 
        /* normalize */
        flt /= pow(10.0f, exp);
        if (flt < 1.0f) {
                flt *= 10.0f;
                exp--;
        }
 
        /* conversion */
        for (i = 0; i < nDigits; i++) {
                flt = flt - (double)digit * 10.0f;
                digit = (int)flt;
                flt *= 10.0f;
                a[i] = digit + '0';
        }
        digit = (int)(flt - (double)digit * 10.0f);
        a[i] = '\0';
 
        /* round up if neccessary */
        i = 0;
        if (digit >= 5)
                i = cvt_round_up(a, nDigits);
 
        /* get decimal point */
        if (decPoint)
                *decPoint = exp + 1 + i;
 
        return a;
}
 
/**
 * libstr_fcvtbuf - Convert double to string.
 * @x - double float variable,
 * @nDigits - count of returned digits AFTER DECIMAL POINT(!),
 * @decPoint - pointer to variable with position of decimal point,
 * @sign - pointer to variable with sign (+ => 0, - => 1),
 * @a - buffer,
 *
 * Size of the buffer should be enough to store all bytes from conversion.
 * The value of double is between 2,2E-308 and 1,8E+308 so
 * 2 * DBL_MAX_10_EXP + 2 bytes are enough.
 * Sometimes value is rouned up if given n-digits variable is less than
 * nominal size of converted string.
 * Function returns a pointer to the @a. Returned string contains whole integer
 * value (base) and fraction with given count of digits (@nDigits).
 */
char *libstr_fcvtbuf(double flt, int nDigits, int *decPoint, int *sign, char *a)
{
        int exp = 0, digit = 0, i = 0;
 
        assert(a);
        assert(nDigits <= DBL_MAX_10_EXP); /* 308 */
 
        /* get sign */
        if (flt < 0.0f && sign) *sign = 1;
        else if (sign) *sign = 0;
 
        /* abs */
        flt = fabs(flt);
 
        /* get exponent */
        exp = (int)log10(flt);
        if (flt >= 1.0f) nDigits += exp+1;
 
        /* normalize */
        flt /= pow(10.0f, exp);
        if (flt < 1.0f) {
                flt *= 10.0f;
                exp--;
        }
 
        /* conversion */
        for (i = 0; i < nDigits; i++) {
                flt = flt - (double)digit * 10.0f;
                digit = (int)flt;
                flt *= 10.0f;
                a[i] = digit + '0';
        }
        digit = (int)(flt - (double)digit * 10.0f);
        a[i] = '\0';
 
        /* round up if neccessary */
        i = 0;
        if (digit >= 5)
                i = cvt_round_up(a, nDigits);
 
        /* get decimal point */
        if (decPoint)
                *decPoint = exp + 1 + i;
 
        return a;
}
 
/**
 * libstr_lecvtbuf - Convert long double to string.
 * @x - long double float variable,
 * @nDigits - count of returned digits,
 * @decPoint - pointer to variable with position of decimal point,
 * @sign - pointer to variable with sign (+ => 0, - => 1),
 * @a - buffer,
 *
 * Size of the buffer should be enough to store all bytes from conversion.
 * The value of long double is between so 3,4E-4932 ÷ 1,2E+4932 so
 * LDBL_MAX_10_EXP + 2 bytes are enough.
 * Sometimes value is rouned up if given n-digits variable is less than
 * nominal size of converted string.
 * Function returns a pointer to the @a, count of used bytes is always equal
 * to @nDigits.
 */
char *libstr_lecvtbuf(long double flt, int nDigits, int *decPoint, int *sign, char *a)
{
        int exp = 0, digit = 0, i = 0;
 
        assert(a);
        assert(nDigits <= LDBL_MAX_10_EXP); /* 308 */
 
        /* get sign */
        if (flt < 0.0f && sign) *sign = 1;
        else if (sign) *sign = 0;
 
        /* abs */
        flt = fabsl(flt);
 
        /* get exponent */
        exp = (int)log10l(flt);
 
        /* normalize */
        flt /= powl(10.0f, exp);
        if (flt < 1.0f) {
                flt *= 10.0f;
                exp--;
        }
 
        /* conversion */
        for (i = 0; i < nDigits; i++) {
                flt = flt - (long double)digit * 10.0f;
                digit = (int)flt;
                flt *= 10.0f;
                a[i] = digit + '0';
        }
        digit = (int)(flt - (long double)digit * 10.0f);
        a[i] = '\0';
 
        /* round up if neccessary */
        i = 0;
        if (digit >= 5)
                i = cvt_round_up(a, nDigits);
 
        /* get decimal point */
        if (decPoint)
                *decPoint = exp + 1 + i;
 
        return a;
}
 
/**
 * libstr_lfcvtbuf - Convert long double to string.
 * @x - long double float variable,
 * @nDigits - count of returned digits AFTER DECIMAL POINT(!),
 * @decPoint - pointer to variable with position of decimal point,
 * @sign - pointer to variable with sign (+ => 0, - => 1),
 * @a - buffer,
 *
 * Size of the buffer should be enough to store all bytes from conversion.
 * The value of long double is between 3,4E-4932 ÷ 1,2E+4932 so
 * 2 * LDBL_MAX_10_EXP + 2 bytes are enough.
 * Sometimes value is rouned up if given n-digits variable is less than
 * nominal size of converted string.
 * Function returns a pointer to the @a. Returned string contains whole integer
 * value (base) and fraction with given count of digits (@nDigits).
 */
char *libstr_lfcvtbuf(long double flt, int nDigits, int *decPoint, int *sign, char *a)
{
        int exp = 0, digit = 0, i = 0;
 
        assert(a);
        assert(nDigits <= LDBL_MAX_10_EXP); /* 308 */
 
        /* get sign */
        if (flt < 0.0f && sign) *sign = 1;
        else if (sign) *sign = 0;
 
        /* abs */
        flt = fabsl(flt);
 
        /* get exponent */
        exp = (int)log10l(flt);
        if (flt >= 1.0f) nDigits += exp+1;
 
        /* normalize */
        flt /= powl(10.0f, exp);
        if (flt < 1.0f) {
                flt *= 10.0f;
                exp--;
        }
 
        /* conversion */
        for (i = 0; i < nDigits; i++) {
                flt = flt - (double)digit * 10.0f;
                digit = (int)flt;
                flt *= 10.0f;
                a[i] = digit + '0';
        }
        digit = (int)(flt - (double)digit * 10.0f);
        a[i] = '\0';
 
        /* round up if neccessary */
        i = 0;
        if (digit >= 5)
                i = cvt_round_up(a, nDigits);
 
        /* get decimal point */
        if (decPoint)
                *decPoint = exp + 1 + i;
 
        return a;
}



Przykłady użycia (zwłaszcza float itp).
/**
 * Enhanced String Library
 * Copyright (c) 2005-2007 Lukasz Cepowski (cepa[at]o2.pl)
 * GNU GPL
 * http://cepa.one.pl/libstr
 */
 
/*$ str_conv.c 2000 2007-03-26 $*/
 
#include <libstr.h>
#include "libstr_internal.h"
#include <float.h>
 
/**
 * str_atoul - String to unsigned 32bit integer.
 */
uint32_t str_atoul(const String *str, int base)
{
        assert(str);
        return libstr_atoul(str->data, base);
}
 
/**
 * str_atol - String to signed 32bit integer.
 */
int32_t str_atol(const String *str, int base)
{
        assert(str);
        return libstr_atol(str->data, base);
}
 
/**
 * str_atoull - String to unsigned 64bit integer.
 */
uint64_t str_atoull(const String *str, int base)
{
        assert(str);
        return libstr_atoull(str->data, base);
}
 
/**
 * str_atoll - String to signed 64bit integer.
 */
int64_t str_atoll(const String *str, int base)
{
        assert(str);
        return libstr_atoll(str->data, base);
}
 
/**
 * str_ultoa - Unsigned 32bit integer to string.
 */
String *str_ultoa(uint32_t x, int base, String *str)
{
        if (!str) str = str_new_block(33);
        else str = str_realloc(str, 33);
        if (!str) return NULL;
        libstr_ultoa(x, base, str->data);
        str = str_align_null(str);
        return str;
}
 
/**
 * str_ltoa - Signed 32bit integer to string.
 */
String *str_ltoa(int32_t x, int base, String *str)
{
        if (!str) str = str_new_block(33);
        else str = str_realloc(str, 33);
        if (!str) return NULL;
        libstr_ltoa(x, base, str->data);
        str = str_align_null(str);
        return str;
}
 
/**
 * str_ulltoa - Unsigned 64bit integer to string.
 */
String *str_ulltoa(uint64_t x, int base, String *str)
{
        if (!str) str = str_new_block(65);
        else str = str_realloc(str, 65);
        if (!str) return NULL;
        libstr_ulltoa(x, base, str->data);
        str = str_align_null(str);
        return str;
}
 
/**
 * str_lltoa - Signed 64bit integer to string.
 */
String *str_lltoa(int64_t x, int base, String *str)
{
        if (!str) str = str_new_block(65);
        else str = str_realloc(str, 65);
        if (!str) return NULL;
        libstr_lltoa(x, base, str->data);
        str = str_align_null(str);
        return str;
}
 
/**
 * str_atod - Convert string to double.
 */
double str_atod(const String *str)
{
        assert(str);
        return libstr_atod(str->data);
}
 
/**
 * str_atold - Convert string to long double.
 */
long double str_atold(const String *str)
{
        assert(str);
        return libstr_atold(str->data);
}
 
/**
 * str_dtoa - Convert double to string (Floating notation).
 */
String *str_dtoa(double x, int nDigits, String *str)
{
        int decPt = 0, sign = 0;
 
        if (!str) str = str_new_block(2 * DBL_MAX_10_EXP + 20);
        else str = str_realloc(str, 2 * DBL_MAX_10_EXP + 20);
        if (!str) return NULL;
 
        libstr_fcvtbuf(x, nDigits, &decPt, &sign, str->data);
        str = str_align_null(str);
 
        if (decPt > 0) {
                str = str_insert_ch(str, '.', decPt);
        } else {
                str = str_repeat_ch(str, '0', 0, -decPt + 1);
                str = str_insert_ch(str, '.', 1);
        }
 
        if (sign == 1) {
                str = str_prepend_ch(str, '-');
        }
 
        return str;
}
 
/**
 * str_dtoae - Convert double to string (Scientific notation).
 */
String *str_dtoae(double x, int nDigits, String *str)
{
        int decPt = 0, sign = 0;
        char buf[10];
 
        if (!str) str = str_new_block(DBL_MAX_10_EXP + 20);
        else str = str_realloc(str, DBL_MAX_10_EXP + 20);
        if (!str) return NULL;
 
        libstr_ecvtbuf(x, nDigits, &decPt, &sign, str->data);
        str = str_align_null(str);
 
        if (decPt > 0) {
                if (decPt > str->strLen) {
                        /* scientific notation */
                        if (str->strLen > 1) str = str_insert_ch(str, '.', 1);
                        libstr_ltoa(decPt-1, 10, buf);
                        str = str_append_ch(str, 'e');
                        str = str_append_cstr(str, buf);
                } else if (decPt < str->strLen) {
                        str = str_insert_ch(str, '.', decPt);
                }
        } else {
                /* scientific notation */
                libstr_ltoa(decPt-1, 10, buf);
                str = str_insert_ch(str, '.', 1);
                str = str_append_ch(str, 'e');
                str = str_append_cstr(str, buf);
        }
 
        if (sign == 1) {
                str = str_prepend_ch(str, '-');
        }
 
        return str;
}
 
/**
 * str_ldtoa - Convert long double to string (Floating notation).
 */
String *str_ldtoa(long double x, int nDigits, String *str)
{
        int decPt = 0, sign = 0;
 
        if (!str) str = str_new_block(2 * LDBL_MAX_10_EXP + 20);
        else str = str_realloc(str, 2 * LDBL_MAX_10_EXP + 20);
        if (!str) return NULL;
 
        libstr_lfcvtbuf(x, nDigits, &decPt, &sign, str->data);
        str = str_align_null(str);
 
        if (decPt > 0) {
                str = str_insert_ch(str, '.', decPt);
        } else {
                str = str_repeat_ch(str, '0', 0, -decPt + 1);
                str = str_insert_ch(str, '.', 1);
        }
 
        if (sign == 1) {
                str = str_prepend_ch(str, '-');
        }
 
        return str;
}
 
/**
 * str_ldtoae - Convert long double to string (Scientific notation).
 */
String *str_ldtoae(long double x, int nDigits, String *str)
{
        int decPt = 0, sign = 0;
        char buf[10];
 
        if (!str) str = str_new_block(LDBL_MAX_10_EXP + 20);
        else str = str_realloc(str, LDBL_MAX_10_EXP + 20);
        if (!str) return NULL;
 
        libstr_lecvtbuf(x, nDigits, &decPt, &sign, str->data);
        str = str_align_null(str);
 
        if (decPt > 0) {
                if (decPt > str->strLen) {
                        /* scientific notation */
                        if (str->strLen > 1) str = str_insert_ch(str, '.', 1);
                        libstr_ltoa(decPt-1, 10, buf);
                        str = str_append_ch(str, 'e');
                        str = str_append_cstr(str, buf);
                } else if (decPt < str->strLen) {
                        str = str_insert_ch(str, '.', decPt);
                }
        } else {
                /* scientific notation */
                libstr_ltoa(decPt-1, 10, buf);
                str = str_insert_ch(str, '.', 1);
                str = str_append_ch(str, 'e');
                str = str_append_cstr(str, buf);
        }
 
        if (sign == 1) {
                str = str_prepend_ch(str, '-');
        }
 
        return str;
}

2 komentarze

natash 2007-04-10 09:26

Naprawde dobry kod, przyda się :) gratulacje i  pzdr

Coldpeer 2007-04-09 13:43

Naprawdę fajne :)