Konwersje liczb

cepa

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 komentarzy

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

Naprawdę fajne :)