float to string для микроконтроллера
Feb. 12th, 2022 01:21 am![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Как и обещал, написал-таки функцию вывода флоатов в строку. Вот, что получилось:
Для пробы сделал вот такой массив:
static const float tests[] = {-1.23456789e-37, -3.14159265e-2, -1234.56789, -1.2345678, 0.1234567, 123.456789, 1.98765e7, 2.473829e31};
И в цикле вывел все его члены с 0..4 знаками после запятой:
На мой взгляд, сгодится.
// be careful: if pow10 would be bigger you should change str[] size!
static const float pwr10[] = {1., 10., 100., 1000., 10000.};
static const float rounds[] = {0.5, 0.05, 0.005, 0.0005, 0.00005};
#define P10L (sizeof(pwr10)/sizeof(uint32_t) - 1)
static char * float2str(float x, uint8_t prec){
if(prec > P10L) prec = P10L;
static char str[16] = {0}; // -117.5494E-36\0 - 14 symbols max!
char *s = str + 14; // go to end of buffer
uint8_t minus = 0;
if(x < 0){
x = -x;
minus = 1;
}
int pow = 0; // xxxEpow
// now convert float to 1.xxxE3y
while(x > 1000.f){
x /= 1000.f;
pow += 3;
}
while(x < 1.){
x *= 1000.f;
pow -= 3;
}
// print Eyy
if(pow){
uint8_t m = 0;
if(pow < 0){pow = -pow; m = 1;}
while(pow){
register int p10 = pow/10;
*s-- = '0' + (pow - 10*p10);
pow = p10;
}
if(m) *s-- = '-';
*s-- = 'E';
}
// now our number is in [1, 1000]
uint32_t units;
if(prec){
units = (uint32_t) x;
uint32_t decimals = (uint32_t)((x-units+rounds[prec])*pwr10[prec]);
// print decimals
while(prec){
register int d10 = decimals / 10;
*s-- = '0' + (decimals - 10*d10);
decimals = d10;
--prec;
}
// decimal point
*s-- = '.';
}else{ // without decimal part
units = (uint32_t) (x + 0.5);
}
// print main units
if(units == 0) *s-- = '0';
else while(units){
register uint32_t u10 = units / 10;
*s-- = '0' + (units - 10*u10);
units = u10;
}
if(minus) *s-- = '-';
return s+1;
}
Для пробы сделал вот такой массив:
static const float tests[] = {-1.23456789e-37, -3.14159265e-2, -1234.56789, -1.2345678, 0.1234567, 123.456789, 1.98765e7, 2.473829e31};
И в цикле вывел все его члены с 0..4 знаками после запятой:
-123E-39 -123.5E-39 -123.46E-39 -123.457E-39 -123.4568E-39 -31E-3 -31.4E-3 -31.42E-3 -31.416E-3 -31.4159E-3 -1E3 -1.2E3 -1.23E3 -1.235E3 -1.2346E3 -1 -1.2 -1.23 -1.235 -1.2346 123E-3 123.5E-3 123.46E-3 123.457E-3 123.4567E-3 123 123.5 123.46 123.457 123.4568 20E6 19.9E6 19.88E6 19.876E6 19.8765E6 25E30 24.7E30 24.74E30 24.738E30 24.7383E30
На мой взгляд, сгодится.