double with 15digits precision?
Hi, what is the reason to limit the precision to 9 digits only?
// limit precision to 9, cause a prec >= 10 can lead to overflow errors
while ((len < PRINTF_FTOA_BUFFER_SIZE) && (prec > 9U)) {
I would be happy to have double float printed with full 15digits precision - is that 9 digits limit an issue with some algorithms used? Thanks for your work!
uint32_t is used for printing, so e9 is limit
You work with double (64bits) already - line 487 - thus the "exponent" is in exp2 (11bits) and "mantissa" (1+52bits) could be stored in an uint64_t M, for example (and then M should be "converted" to int64_t by the code as is, and printed out) :
union {
uint64_t U;
double F;
} conv;
conv.F = value;
uint64_t M = (conv.U & 0x800F_FFFF_FFFF_FFFF) ; <<<<<<<<<< Mantissa for example
int exp2 = (int)((conv.U >> 52U) & 0x07FFU) - 1023; // effectively log2
I think everything is there already, some tweaking, perhaps..
here is fractional part printing: https://github.com/mpaland/printf/blob/master/printf.c#L413
I added to the pow[] array the powers of up to 10^15 and changed the precision to 15, but still I get wrong results, usually the first 5-6 decimal places are zero, ie. like
PI= 3.000000466742562e+00
A= -1.000002554368448e+08
1 xyz = 8.000001902844712e-01
2 xyz = 1.000000317619429e+00
3 xyz = 2.000001240909688e+00
4 xyz = 3.000002166359860e+00
5 xyz = 4.000003089594626e+00
6 xyz = 5.000004013904494e+00
7 xyz = 6.000000643134767e+00
8 xyz = 7.000001567591462e+00
9 xyz = 8.000002491627471e+00
ok, this looks better:
PI= 3.141592653589793e+00 // 3.141592653589793
A= -1.234567891233759e+08 // -123456789.12345678
9 degree Calculator test started.. wait... // asin(acos(atan(tan(cos(sin(degree))))))) in DEG mode
1 degree = 1.000000001957684e+00 hex= 0x3ff00000008687f3
2 degree = 1.999999999819259e+00 hex= 0x3ffffffffff3945f
3 degree = 2.999999998867262e+00 hex= 0x4007ffffffd91454
4 degree = 4.000000000341832e+00 hex= 0x401000000005df65
5 degree = 4.999999999327491e+00 hex= 0x4013fffffff47246
6 degree = 5.999999999520980e+00 hex= 0x4017fffffff7c53f
7 degree = 6.999999999588305e+00 hex= 0x401bfffffff8ed59
8 degree = 7.999999999946748e+00 hex= 0x401fffffffff15cb
9 degree = 8.999999999832568e+00 hex= 0x4021fffffffe8fd0
With uint64_t instead of unsigned long
int whole = (int)value;
double tmp = (value - whole) * pow10[prec];
uint64_t frac = (uint64_t)tmp;
diff = tmp - frac;
@ledvinap : Is there any good reason to limit this to uint32_t and 1e9? I mean, uint64_t's are used elsewhere in printf.c after all.
@eyalroz, @ledvinap Thanks so much for this massive amount of input from you guys! Right now I'm just too busy with another project, I'll get back to printf in August. Promised.
@mpaland : If you do, please email me and let's chat, as my fork currently integrates most other people's contributions...