97 lines
2.3 KiB
C
97 lines
2.3 KiB
C
/* ************************************************************************** */
|
|
/* _____ _ */
|
|
/* bcd/to_ascii.c |_ _|__ _ _| |__ ___ _ _ */
|
|
/* | Project: libg1m | |/ _ \| | | | '_ \ / _ \ | | | */
|
|
/* | | (_) | |_| | | | | __/ |_| | */
|
|
/* By: thomas <thomas@touhey.fr> |_|\___/ \__,_|_| |_|\___|\__, |.fr */
|
|
/* Last updated: 2016/11/21 13:54:41 |___/ */
|
|
/* */
|
|
/* ************************************************************************** */
|
|
#include <libg1m/internals/bcd.h>
|
|
#define VISIBLE_PRECISION 5
|
|
|
|
/**
|
|
* g1m_bcdtoa:
|
|
* Simple BCD to string function.
|
|
*
|
|
* @arg bcd The BCD number.
|
|
* @return The allocated string.
|
|
*/
|
|
|
|
char *g1m_bcdtoa(struct bcd *bcd)
|
|
{
|
|
char buf[50], *p = buf;
|
|
unsigned char *bytes = bcd->BCDval;
|
|
|
|
/* get the exponent */
|
|
int neg = 0;
|
|
int exp = g1m_bcd_get_exponent_neg(bcd, &neg);
|
|
if (neg) *p++ = '-';
|
|
|
|
/* get the mantissa */
|
|
char mant[15];
|
|
for (int i = 0; i < 15; i += 2)
|
|
mant[i] = lwr(i / 2 + 1);
|
|
for (int i = 1; i < 15; i += 2)
|
|
mant[i] = upr(i / 2 + 2);
|
|
|
|
/* calculate number of significant digits */
|
|
int signif;
|
|
for (signif = 15; signif && !mant[signif - 1]; signif--);
|
|
if (!signif) exp = 0;
|
|
|
|
/* put integer part */
|
|
int num = 0;
|
|
if (exp > 0) {
|
|
while (exp > 0 && signif) {
|
|
exp--;
|
|
signif--;
|
|
*p++ = mant[num++] + '0';
|
|
}
|
|
if (exp > 0 && exp < VISIBLE_PRECISION) while (exp) {
|
|
exp--;
|
|
*p++ = '0';
|
|
}
|
|
} else
|
|
*p++ = '0';
|
|
|
|
/* put decimal part */
|
|
if (signif) {
|
|
*p++ = '.';
|
|
/* put some zeroes */
|
|
if (exp < 0 && exp > -VISIBLE_PRECISION) while (exp) {
|
|
exp++;
|
|
*p++ = '0';
|
|
}
|
|
/* put the numbers */
|
|
while (signif--)
|
|
*p++ = mant[num++] + '0';
|
|
}
|
|
|
|
/* put exponent */
|
|
if (exp) {
|
|
*p++ = '^';
|
|
int exp_neg = exp < 0;
|
|
if (exp_neg) {
|
|
*p++ = '(';
|
|
*p++ = '-';
|
|
exp = -exp;
|
|
}
|
|
int eprec = 100;
|
|
while (exp < eprec)
|
|
eprec /= 10;
|
|
while (eprec) {
|
|
*p++ = exp / eprec + '0';
|
|
exp %= eprec;
|
|
eprec /= 10;
|
|
}
|
|
if (exp_neg) *p++ = ')';
|
|
}
|
|
|
|
/* put string end */
|
|
*p = 0;
|
|
|
|
/* duplicate and send to user */
|
|
return (strdup(buf));
|
|
}
|