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;
}
Naprawde dobry kod, przyda się :) gratulacje i pzdr
Naprawdę fajne :)