Search code examples
rfloating-pointdoublelimitnotation

Why does the required resulting string length for sprintf("%.8190f", .Machine$double.xmax) or sprintf("%.8190f", (2-2^(-52))*2^1023) equal to 8500?


In normalized double precision representation, thinking "1." of "1.f" in fractional part leads us to reduce sprintf maximal from 8192 to 8190.

Now;

identical(.Machine$double.xmax, (2-2^(-52))*2^1023) # TRUE

sprintf("%.8190f", .Machine$double.xmax)
# Error in sprintf("%.8190f", .Machine$double.xmax) : required resulting string length 8500 is greater than maximal 8192

sprintf("%.8190f", (2-2^(-52))*2^1023)
# Error in sprintf("%.8190f", (2 - 2^(-52)) * 2^1023) : required resulting string length 8500 is greater than maximal 8192

sprintf("%.8190f", .Machine$double.xmax- 10^308)
# Error in sprintf("%.8190f", .Machine$double.xmax - 10^308) : required resulting string length 8499 is greater than maximal 8192

sprintf("%.7882f", -.Machine$double.xmax) 
# Error in sprintf("%.7882f", -.Machine$double.xmax) : required resulting string length 8193 is greater than maximal 8192
sprintf("%.7881f", -.Machine$double.xmax) # Seamlessly shows the result.

(2-2^(-52) ) 2^1023 ≈ 1,797693 x 10^308. So, where does this 8500 in sprintf output materialize from?

Also, the Value of sprintf is: A character vector of length that of the longest input. If any element of fmt or any character argument is declared as UTF-8, the element of the result will be in UTF-8 and have the encoding declared as UTF-8. Otherwise it will be in the current locale's encoding.

So, sprintf seems not to give the 64-bit double precesion floating point representation of a numeric value?


Solution

  • The ”%.nf” format produces a negative sign if needed, the integer decimal digits of the number being printed, a period, and as many decimal digits as specified by n. Thus, for the greatest representable finite value around 1.797693•10308, %.8190f would produce 309 digits, one decimal point, and 8,190 zeros after the decimal point, totaling 8,500 characters.

    As confirmation, observe the result of nchar(sprintf("%.100f", .Machine$double.xmax)) is 410, for 309 digits, one decimal point, and 100 zeros after the decimal point.