Re: sprintf() precision arbitrarily at six decimal places?
- Posted by petelomax Apr 30, 2019
- 1607 views
Pete, feel free to jump in here. This behavior also occurs with Phix.
You have not actually explained what your problem is:
There are many, many, many different uses of numbers.
Why exactly do you need variable precision outputs?
Anyway, here's what I have:
What's the best way to insure all decimal places are returned without going scientific notation for very-precise values?
IEEE 754 floats are not exact and hence when using them "all decimal places" is simply meaningless (see link).
atom w = 0.123456789123456789123456789 -- ...^^^ ==> ...68(ish) [on 32-bit]
Phix limits the precision to 16 on 32-bit and 20 on 64-bit, as that is the underlying hardware limit, and which is why sprintf("%0.25f",{w}) yields "0.1234567891234568" on Phix whereas OE yields "0.1234567891234568100000000".
The latter trailing "100000000" is completely meaningless. The definition of atom w rounded the second "678" to "68" plus some random leftover because it is stored in base 2 rather than base 10.
The default precision of sprintf() is 6, whereas the fixed precision of sprint() is 10. Note however that %g does trim trailing zeroes (and sometimes goes all e-notation on you) whereas %f does not.
If you use mpfr you can invoke (eg) mpfr_set_default_prec() to set the precision held.
Note however you are still expected to stipulate the printing precision when invoking mpfr_sprintf(), and that mpfr is an extension of IEEE 754 and hence still technically not exact, just allowing a higher precision/less inaccuracy.
If you use bigatom you can invoke (eg) ba_scale() to set the precision held.
Note however you are still expected to stipulate the printing precision when invoking ba_sprintf(), though it is a bcd-based library and therefore holds eg ba_new("0.123456789123456789123456789") exactly [using a string is deliberate] and ba_sprint() returns "the whole thing", which may be what you are after. It is significantly slower than mpfr though.
I sometimes use ad-hoc routines such as the following to smarten things up:
function smartp(atom N) string res if N=floor(N) then return sprintf("%d",N) end if res = sprintf("%12f",round(N,1000000)) if find('.',res) then res = trim_tail(res,"0") res = trim_tail(res,".") end if return res end function
PS: 0.8.0 introduced a new printf settings option, printf(0,"",{"unicode_align",true}) and I could easily add a few other options such as min/max d.p.