Discussion:
printf %f - limiting the size of the outputted string ?
(too old to reply)
R.Wieser
2019-08-08 11:52:31 UTC
Permalink
Hello all,

I've been caught out a few times by an unexpected long result while printing
a float into a buffer using a "sprintf" function (several available, in (at
least) five different DLLs).

So, I did a google to determine the absolute maximum-to-be-expected size of
the outputted string, and found this:
https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/

But even the size for a simple 8 byte float (standard under Windows) is a
whopping 309 chars.

Hence my question: Is there a method/function which limits the outputted
length ? Something that will use the scientific "E" notation will do
fine.

Regards,
Rudy Wieser
acc
2019-08-08 21:51:28 UTC
Permalink
Post by R.Wieser
Hello all,
I've been caught out a few times by an unexpected long result while printing
a float into a buffer using a "sprintf" function (several available, in (at
least) five different DLLs).
So, I did a google to determine the absolute maximum-to-be-expected size of
https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/
But even the size for a simple 8 byte float (standard under Windows) is a
whopping 309 chars.
Hence my question: Is there a method/function which limits the outputted
length ? Something that will use the scientific "E" notation will do
fine.
%g use the shortest representation: %e or %f
in %g the precision parameter control the number of significant digits
(not decimals as in %f) displayed:
printf("%.3g", 3.1415926); --> 3.14 (3 significant digits)
R.Wieser
2019-08-09 08:36:13 UTC
Permalink
acc,
Post by acc
%g use the shortest representation: %e or %f
Yes, but that one seems to work for CRTDLL.DLL only (the other DLLs do not
seem to recognise the format, and just print "g"). Also, I see no
mentioning of the maximum number of chars outputted.

A quick test printing "123456789.0" using "%g" returns "1.23457e+008". Is
that, 12 chars, all I need to recon with ?

Whoops, no. 13 chars (almost forgot the account for a possible minus sign).

Regards,
Rudy Wieser
acc
2019-08-09 18:58:45 UTC
Permalink
Post by R.Wieser
Yes, but that one seems to work for CRTDLL.DLL only (the other DLLs do not
seem to recognise the format, and just print "g"). Also, I see no
mentioning of the maximum number of chars outputted.
You must use crt, those in Windows's API don't recognize double.
acc
2019-08-09 19:23:01 UTC
Permalink
Post by acc
You must use crt, those in Windows's API don't recognize double.
Sorry, i meant floating point, so it applies to float and double.
R.Wieser
2019-08-10 08:43:24 UTC
Permalink
acc,
Post by acc
You must use crt, those in Windows's API don't recognize double.
I thought I had checked that, but somehow something went awry I got the
wrong idea. Sorry.

But yes, the Windows APIs do not recognise floats /at all/. Regardless of
doubles or singles (and the latter still wonders me).
Post by acc
Sorry, i meant floating point, so it applies to float and double.
:-) Yup. And no 10-byte floats either (x86 FPU native). :-p

Regards,
Rudy Wieser

JJ
2019-08-09 00:58:55 UTC
Permalink
Post by R.Wieser
Hello all,
I've been caught out a few times by an unexpected long result while printing
a float into a buffer using a "sprintf" function (several available, in (at
least) five different DLLs).
So, I did a google to determine the absolute maximum-to-be-expected size of
https://www.exploringbinary.com/maximum-number-of-decimal-digits-in-binary-floating-point-numbers/
But even the size for a simple 8 byte float (standard under Windows) is a
whopping 309 chars.
Hence my question: Is there a method/function which limits the outputted
length ? Something that will use the scientific "E" notation will do
fine.
Regards,
Rudy Wieser
A 64-bit float value can only have 15-16 of significant digits. How did it
end up having 309 characters?
R.Wieser
2019-08-09 09:03:41 UTC
Permalink
JJ,
Post by JJ
A 64-bit float value can only have 15-16 of significant digits.
How did it end up having 309 characters?
Significant digits + a lot of zeroes following it ?

I took my clue from the webpage I linked to. I'm not all that good with
formulae, but take a peek at the one below the line "It has 309
(significant) digits. You can count them, or use this formula:"

Though I think that there might be a slight difference in your and their
usage of the word "significant".


Another page I've got stored,
http://en.wikipedia.org/wiki/Double_precision_floating-point_format , shows,
in its example for "(Max. Double)", a multiplier of 10^308 . Which does
seem to confirm that 309 chars number.

Regards,
Rudy Wieser
JJ
2019-08-09 14:11:08 UTC
Permalink
Post by R.Wieser
JJ,
Post by JJ
A 64-bit float value can only have 15-16 of significant digits.
How did it end up having 309 characters?
Significant digits + a lot of zeroes following it ?
I took my clue from the webpage I linked to. I'm not all that good with
formulae, but take a peek at the one below the line "It has 309
(significant) digits. You can count them, or use this formula:"
Though I think that there might be a slight difference in your and their
usage of the word "significant".
Another page I've got stored,
http://en.wikipedia.org/wiki/Double_precision_floating-point_format , shows,
in its example for "(Max. Double)", a multiplier of 10^308 . Which does
seem to confirm that 309 chars number.
That's the maximum exponent. The significant digits came from the value
stored in the fraction field - which is only limited to 52-bit.

<https://en.wikipedia.org/wiki/Double_precision_floating-point_format#IEEE_754_double-precision_binary_floating-point_format:_binary64>

[quote]
The 53-bit significand precision gives from 15 to 17 significant decimal
digits precision (2eāˆ’53 ā‰ˆ 1.11 Ɨ 10eāˆ’16).
[/quote]

Even though the float can represent more than 17 digits, the remaining 18+
digits may no longer be accurate because the precision is limited to 52
bits. They usually end up as repeating digits or set of digits, if the float
number is odd.
JJ
2019-08-09 14:13:53 UTC
Permalink
Have you checked `StringCbPrintf()` function of the C runtime library (from
`strsafe.h`), BTW?
R.Wieser
2019-08-09 18:59:52 UTC
Permalink
JJ,
Post by JJ
That's the maximum exponent.
I think I already mentioned that your and the websites definition might be
different ...

But back to the problem:

309 output chars is /way/ to much to my liking. I tried "%g" too but that
one causes the output to be both too short and, with smaller integer
numbers, doesn't even print a fractional part - which causes the output to
become hard to recognise as a float result.

In the end checked the exponent myself (ANDing it off), defaulting to the %f
format, but changing to the %e one when the exponent becomes either too
small or large. For larg numbers thats 17 chars in the integer part (yep,
/that/ 17), for small ones when the fractional part (with a 5 char
precision) becomes almost zero.
Post by JJ
Have you checked 'StringCbPrintf()' function of the C runtime
library (from 'strsafe.h'), BTW?
I'm afraid that CRTDLL.DLL in C:\Windows\System32 is the only C runtime I
have on this (XPsp3) machine.

Regards,
Rudy Wieser
Kaz Kylheku
2019-08-09 13:44:59 UTC
Permalink
Post by JJ
A 64-bit float value can only have 15-16 of significant digits. How did it
end up having 309 characters?
By avoiding exponential notation, and writing out the full decimal
expansion.

This is the TXR Lisp interactive listener of TXR 222.
Quit with :quit or Ctrl-D on empty line. Ctrl-X ? for cheatsheet.
1> (format t "~f\n" 1E308)
1000000000000000010979063629440455417404923096773118463368106829031575854049114
9153716332897849468889906124966972117251561159028374314008832830700919814604603
1271664502933027185697489699588559043338384466165001178426897626212945177628091
195786707458122783970171784415105291802893207873272974885715430223118336.000
--
TXR Programming Lanuage: http://nongnu.org/txr
Music DIY Mailing List: http://www.kylheku.com/diy
ADA MP-1 Mailing List: http://www.kylheku.com/mp1
Loading...