eddy_em: (Default)
[personal profile] eddy_em
Как и обещал, написал-таки функцию вывода флоатов в строку. Вот, что получилось:

// 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


На мой взгляд, сгодится.

May 2025

S M T W T F S
    123
45678910
11121314151617
1819202122 2324
25262728293031

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated May. 24th, 2025 09:11 am
Powered by Dreamwidth Studios