// // Created by cfif on 26.10.22. // #include static unsigned char * cvtround (double fract, int *exp, unsigned char *start, unsigned char *end, unsigned char ch, unsigned char *negp) { double tmp; if (fract) { modf (fract * 10, &tmp); } else { tmp = ch - '0'; } if (tmp > 4) { for (;; --end) { if (*end == '.') { --end; } if (++*end <= '9') { break; } *end = '0'; if (end == start) { if (exp) { /* e/E; increment exponent */ *end = '1'; ++*exp; } else { /* f; add extra digit */ *--end = '1'; --start; } break; } } } else if (*negp) { /* * ``"%.3f", (double)-0.0004'' gives you a negative 0. */ for (;; --end) { if (*end == '.') { --end; } if (*end != '0') { break; } if (end == start) { *negp = 0; } } } return start; } static unsigned char * exponent (unsigned char *p, int exp, unsigned char fmtch) { unsigned char expbuf [8], *t; *p++ = fmtch; if (exp < 0) { exp = -exp; *p++ = '-'; } else { *p++ = '+'; } t = expbuf + sizeof(expbuf); if (exp > 9) { do { *--t = exp % 10 + '0'; } while ((exp /= 10) > 9); *--t = exp + '0'; for (; t < expbuf + sizeof(expbuf); *p++ = *t++) continue; } else { *p++ = '0'; *p++ = exp + '0'; } return p; } static int cvt (double number, int prec, int sharpflag, unsigned char *negp, unsigned char fmtch, unsigned char *startp, unsigned char *endp) { unsigned char *p, *t; double fract; int dotrim, expcnt, gformat; double integer, tmp; expcnt = 0; dotrim = expcnt = gformat = 0; fract = modf (number, &integer); /* * get an extra slot for rounding */ t = ++startp; /* * get integer portion of number; put into the end of the buffer; the * .01 is added for modf (356.0 / 10, &integer) returning .59999999... */ for (p = endp - 1; integer; ++expcnt) { tmp = modf (integer / 10, &integer); *p-- = (int) ((tmp + .01) * 10) + '0'; } switch (fmtch) { case 'f': /* reverse integer into beginning of buffer */ if (expcnt) { for (; ++p < endp; *t++ = *p); } else { *t++ = '0'; } /* * if precision required or alternate flag set, add in a * decimal point. */ if (prec || sharpflag) { *t++ = '.'; } /* * if requires more precision and some fraction left */ if (fract) { if (prec) { do { fract = modf (fract * 10, &tmp); *t++ = (int)tmp + '0'; } while (--prec && fract); } if (fract) { startp = cvtround (fract, 0, startp, t - 1, '0', negp); } } for (; prec--; *t++ = '0'); break; case 'e': case 'E': eformat: if (expcnt) { *t++ = *++p; if (prec || sharpflag) { *t++ = '.'; } /* * if requires more precision and some integer left */ for (; prec && ++p < endp; --prec) { *t++ = *p; } /* * if done precision and more of the integer component, * round using it; adjust fract so we don't re-round * later. */ if (! prec && ++p < endp) { fract = 0; startp = cvtround (0, &expcnt, startp, t - 1, *p, negp); } /* * adjust expcnt for digit in front of decimal */ --expcnt; } /* * until first fractional digit, decrement exponent */ else if (fract) { /* * adjust expcnt for digit in front of decimal */ for (expcnt = -1;; --expcnt) { fract = modf (fract * 10, &tmp); if (tmp) { break; } } *t++ = (int)tmp + '0'; if (prec || sharpflag) { *t++ = '.'; } } else { *t++ = '0'; if (prec || sharpflag) { *t++ = '.'; } } /* * if requires more precision and some fraction left */ if (fract) { if (prec) { do { fract = modf (fract * 10, &tmp); *t++ = (int)tmp + '0'; } while (--prec && fract); } if (fract) { startp = cvtround (fract, &expcnt, startp, t - 1, '0', negp); } } /* * if requires more precision */ for (; prec--; *t++ = '0'); /* * unless alternate flag, trim any g/G format trailing 0's */ if (gformat && ! sharpflag) { while (t > startp && *--t == '0'); if (*t == '.') { --t; } ++t; } t = exponent (t, expcnt, fmtch); break; case 'g': case 'G': /* * a precision of 0 is treated as a precision of 1 */ if (!prec) { ++prec; } /* * ``The style used depends on the value converted; style e * will be used only if the exponent resulting from the * conversion is less than -4 or greater than the precision.'' * -- ANSI X3J11 */ if (expcnt > prec || (! expcnt && fract && fract < .0001)) { /* * g/G format counts "significant digits, not digits of * precision; for the e/E format, this just causes an * off-by-one problem, i.e. g/G considers the digit * before the decimal point significant and e/E doesn't * count it as precision. */ --prec; fmtch -= 2; /* G->E, g->e */ gformat = 1; goto eformat; } /* * reverse integer into beginning of buffer, * note, decrement precision */ if (expcnt) { for (; ++p < endp; *t++ = *p, --prec); } else { *t++ = '0'; } /* * if precision required or alternate flag set, add in a * decimal point. If no digits yet, add in leading 0. */ if (prec || sharpflag) { dotrim = 1; *t++ = '.'; } else { dotrim = 0; } /* * if requires more precision and some fraction left */ while (prec && fract) { fract = modf (fract * 10, &tmp); *t++ = (int)tmp + '0'; prec--; } if (fract) { startp = cvtround (fract, 0, startp, t - 1, '0', negp); } /* * alternate format, adds 0's for precision, else trim 0's */ if (sharpflag) { for (; prec--; *t++ = '0'); } else if (dotrim) { while (t > startp && *--t == '0'); if (*t != '.') { ++t; } } } return(t - startp); } char *fromFloat(char *bufFloat, float *value) { int flag = 0; if (*value < 0) { flag = 1; *value *= -1; } cvt(*value, 6, 1, bufFloat, 'f',&bufFloat[0], &bufFloat[24]); if (flag) { bufFloat[0] = '-'; } else { bufFloat[0] = ' '; } return bufFloat; }