### 1. sprintf() precision arbitrarily at six decimal places?

Is there a reason the sprintf() precision is 6?

```include std/console.e
include std/text.e
atom v = 0.442404149
puts(1,"\n" & sprint(v))
puts(1,"\n" & sprintf("%f",{v}))
printf(1,"\n%f",{v})
```

```0.442404149
0.442404
0.442404
```

Why?!?! This has caused much agony.

ADD: What's the best way to insure all decimal places are returned without going scientific notation for very-precise values?

### 2. Re: sprintf() precision arbitrarily at six decimal places?

"Slide-rule accuracy" should be enough for everyone.

```include std/math.e

? PI
printf(1, "%f\n", PI )
printf(1, "%30.15f\n", PI )

puts(1,  sprintf("%f", PI ) & "\n" )
puts(1,  sprintf("%.50f", PI ) )
```

```3.141592654
3.141593
3.141592653589793
3.141593
3.14159265358979311599796346854418516159057617187500
```

_tom

### 3. Re: sprintf() precision arbitrarily at six decimal places?

_tom said...

"Slide-rule accuracy" should be enough for everyone.

This might be true.

However, we need at least documentation saying that printf() and sprintf() will arbitrarily lop off the numbers after 6 decimal places.

Best case scenario: The number I feed to printf()/sprintf() is actually returned in its entirety! Is it too late to change this?

### 4. Re: sprintf() precision arbitrarily at six decimal places?

Even ? is not reliable?

```include std/console.e
include std/text.e

atom v = 0.442404149
atom w = 0.123456789123456789123456789

?v
puts(1,"\n")
print(1,v)
puts(1,"\n" & sprint(v))
puts(1,"\n" & sprintf("%0.15f",{v}))
puts(1,"\n" & sprintf("%0.25f",{w}))
printf(1,"\n%f",{v})

puts(1,"\n\n")
?w
puts(1,"\n")
print(1,w)
puts(1,"\n" & sprint(w))
puts(1,"\n" & sprintf("%0.15f",{w}))
puts(1,"\n" & sprintf("%0.25f",{w}))
printf(1,"\n%f",{w})

puts(1,"\n\n")
maybe_any_key()
```

```0.442404149

0.442404149
0.442404149
0.442404149000000
0.1234567891234568100000000
0.442404

0.1234567891

0.1234567891
0.1234567891
0.123456789123457
0.1234567891234568100000000
0.123457
```

### 5. Re: sprintf() precision arbitrarily at six decimal places?

Pete, feel free to jump in here. This behavior also occurs with Phix.

### 6. Re: sprintf() precision arbitrarily at six decimal places?

euphoric said...

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:

euphoric said...

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.

### 7. Re: sprintf() precision arbitrarily at six decimal places?

petelomax said...
euphoric said...

Pete, feel free to jump in here. This behavior also occurs with Phix.

You have not actually explained what your problem is:
... Why exactly do you need variable precision outputs?

I have an atom of value with 8 decimal places. When I want to use it in an API call, I have to make it text; I generally use sprintf("%f",{v}) because I cannot have exponential notation. However, I just recently discovered that sprintf() and sprint() do not return my complete number! I was shocked to discover this.

petelomax said...
euphoric said...

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).

What's the maximum precision I can get away with and still be confident that the number I want is the number I'll get?

I think you answer below... 16 digits. I can run with that.

petelomax said...
```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".

### 8. Re: sprintf() precision arbitrarily at six decimal places?

euphoric said...

I have an atom of value with 8 decimal places. When I want to use it in an API call, I have to make it text; I generally use sprintf("%f",{v}) because I cannot have exponential notation. However, I just recently discovered that sprintf() and sprint() do not return my complete number! I was shocked to discover this.

I suspected as much. You really should hold the precise number it needs and specify that as eg %.8f - I remember having much trouble trying to figure out how many dp each of the various API args needed, especially when the requirements for the same field often changed from one call to the next.

euphoric said...

What's the maximum precision I can get away with and still be confident that the number I want is the number I'll get?

I think you answer below... 16 digits. I can run with that.

Be warned: some of those API calls kicked me for passing too many trailing zeroes.
Independently of that, using the max 16dp can trigger the odd 0.1234000000000001 whereas using say 12 dp would round that glitch away.

### 9. Re: sprintf() precision arbitrarily at six decimal places?

https://www.exploringbinary.com/decimal-precision-of-binary-floating-point-numbers/ A float single-precision has a decimal "precision" of about six figures. A float double-precision gives you about fifteen figures.

Euphoria 1.0 ( era of 16-bit computers) suggests that the "six" figures of sprintf) was inspired by the hardware of the time.

The ten digits of sprint) in oE std/lib looks like someone just liked the number "ten". You can edit sprint) to have a different default.

It is easy to forget that a decimal value you are thinking about is converted to binary and then converted back to decimal. Not all values survive this round-trip.

The oE sprintf) will create fake digits for you; as many fake digits as you wish! This has to be described as a bug. The Phix sprintf) does not do this.

To have sprintf) return a "value in its entirety" is not realistic. It is wrong to believe that values in computer hardware are genuine and accurate values.

My reference to "slide-rule" accuracy refers to a time when you had to think about the values you were using; now computers just spit out lots of digits.

And ... what Pete says.

_tom

### 10. Re: sprintf() precision arbitrarily at six decimal places?

petelomax said...
euphoric said...

I have an atom of value with 8 decimal places. When I want to use it in an API call, I have to make it text; I generally use sprintf("%f",{v}) because I cannot have exponential notation. However, I just recently discovered that sprintf() and sprint() do not return my complete number! I was shocked to discover this.

You really should hold the precise number it needs and specify that as eg %.8f - I remember having much trouble trying to figure out how many dp each of the various API args needed, especially when the requirements for the same field often changed from one call to the next.

Be warned: some of those API calls kicked me for passing too many trailing zeroes.

Yes, and that's why I can't use a one-size-fits-all "%.8f" string. So, I'm just going out to 15 dp and lopping off the extra zeroes, then truncating to the dp that is actually required.

petelomax said...

Independently of that, using the max 16dp can trigger the odd 0.1234000000000001 whereas using say 12 dp would round that glitch away.

I'll keep an eye out for that.

Not signed in.