[Rd] prettyNum digits=0 not compatible with scientific notation
Martin Maechler
m@ech|er @end|ng |rom @t@t@m@th@ethz@ch
Fri Mar 22 18:07:26 CET 2019
>>>>> peter dalgaard
>>>>> on Fri, 22 Mar 2019 17:30:19 +0100 writes:
> FWIW, it doesn't seem to be happening on Mac OS:
>> format(2^30, digits=0)
> [1] "1.e+09"
>> prettyNum(12345.6, digits=0)
> [1] "1.e+04"
> A glibc misfeature?
It seems (and note we are talking about format.default() here,
of which prettyNum() is only a wrapper in this case):
Here's an example that shows that 'digits=0' actually can make
"sense" contrary to what I've claimed previously::
nn <- 123456*10^(0:-8); dd <- c(10, 7, 2:0); names(dd) <- paste0("d=",dd)
sapply(dd, function(dig) sapply(nn, format, digits=dig))
gives (on Linux R 3.5.3, Fedora 28)
d=10 d=7 d=2 d=1 d=0
[1,] "123456" "123456" "123456" "1e+05" "%#4.0-1e"
[2,] "12345.6" "12345.6" "12346" "12346" "%#4.0-1e"
[3,] "1234.56" "1234.56" "1235" "1235" "1235"
[4,] "123.456" "123.456" "123" "123" "123"
[5,] "12.3456" "12.3456" "12" "12" "12"
[6,] "1.23456" "1.23456" "1.2" "1" "1"
[7,] "0.123456" "0.123456" "0.12" "0.1" "0"
[8,] "0.0123456" "0.0123456" "0.012" "0.01" "0"
[9,] "0.00123456" "0.00123456" "0.0012" "0.001" "0"
but probably looks better on Mac
and on our "Windows Server x64 (build 14393)",
for both Platforms
i386-w64-mingw32/i386 (32-bit)
x86_64-w64-mingw32/x64 (64-bit)
is slightly "better":
d=10 d=7 d=2 d=1 d=0
[1,] "123456" "123456" "123456" "1e+05" "1.234560e+05"
[2,] "12345.6" "12345.6" "12346" "12346" "1.234560e+04"
[3,] "1234.56" "1234.56" "1235" "1235" "1235"
[4,] "123.456" "123.456" "123" "123" "123"
[5,] "12.3456" "12.3456" "12" "12" "12"
[6,] "1.23456" "1.23456" "1.2" "1" "1"
[7,] "0.123456" "0.123456" "0.12" "0.1" "0"
[8,] "0.0123456" "0.0123456" "0.012" "0.01" "0"
[9,] "0.00123456" "0.00123456" "0.0012" "0.001" "0"
... interesting ...
Martin
>> On 22 Mar 2019, at 10:10 , Martin Maechler <maechler using stat.math.ethz.ch> wrote:
>>
>> Thank you, Robert for raising this here !
>>
>>>>>>> Robert McGehee
>>>>>>> on Thu, 21 Mar 2019 20:56:19 +0000 writes:
>>
>>> R developers,
>>> Seems I get a bad result ("%#4.0-1e" in particular) when trying to use prettyNum digits=0 with scientific notation. I tried on both my Linux box and on an online R evaluator and saw the same problem, so it's not limited to my box at least. I see the problem in both R 3.5.3 and R 3.3.2.
>>
>>> options(scipen= -100)
>>
>> The above is extreme: You're basically setting an option to
>> always see non-integer numbers in "scientific" format ..
>> But read below about what 'digits' means in this case.
>>
>>> prettyNum(1, digits=0)
>>> [1] "%#4.0-1e"
>>> prettyNum(2, digits=0)
>>> [1] "%#4.0-1e"
>>> prettyNum(1, digits=0, scientific=FALSE) # Works
>>> [1] "1"
>>> prettyNum(1:2, digits=0) # Works
>>> [1] "1" "2"
>>> prettyNum(c(1.1, 2.1), digits=0)
>>> [1] "%#4.0-1e" "%#4.0-1e"
>>> prettyNum(c(1.1, 2.1), digits=1) # Works
>>> [1] "1e+00" "2e+00"
>>
>> I'm the scape goat / culprit /.. : I have worked on tweaking the
>> formatting of (non integer) numbers in R for a long time, on the
>> way introducing prettyNum(), also already long ago...
>> but then it's actually not prettyNum() but rather format() here :
>>
>> Have you read its help page - *with* care?
>>
>> If you do, you'd notice that 'digits' is not among the formal arguments
>> of prettyNum() *and* that prettyNum() passes all its `...` to format().
>> And if you read ?format [which then you should to understand 'digits' !]
>> you see
>>
>>> digits: how many significant digits are to be used for numeric and
>>> complex ‘x’. The default, NULL, uses ‘getOption("digits")’.
>>> This is a suggestion: enough decimal places will be used so that
>>> the smallest (in magnitude) number has this many significant
>>> digits, and also to satisfy ‘nsmall’.
>>
>>> [.....]
>>
>> So, for the real numbers you use in your example, digits are
>> *significant* digits as in 'options(digits= *)' or
>> 'print(.., digits= *)'
>>
>> ------ Excursion about 'integer' and format()ing ------------
>> -- and you now may also understand why prettyNum(1:2, digits=0) works
>> as you expect: integer formatting behaves differently ....
>> but I acknowledge that the ?format help page does not say so
>> explicitly yet: it 'real and complex' numbers for the
>> 'scientific' argument, and 'numeric and complex' numbers for
>> the 'format' argument.
>> If you replac numeric by reald, what this entails (by logic)
>> that 'integer' numbers are *not* affected by 'digits' nor 'scientific'.
>>
>> But there's yet more subtlety: 'integer' here means class/type "integer"
>> and not just an integer number, i.e., the difference of 1L and 1 :
>>
>>> str(1)
>> num 1
>>> str(1L)
>> int 1
>>> str(1:3)
>> int [1:3] 1 2 3
>>> str(1:3 + 0)
>> num [1:3] 1 2 3
>>>
>> ------ end of Excursion{'integer' ..} -------------------------------
>>
>> Back to real numbers : 'digits' are used as *significant* digits
>> (and are only a suggestion: format() and prettyNum() ensure
>> a common width for their resulting strings so printing will be
>> nicely aligned), see e.g.
>>
>>> format(3.14, scientific=FALSE)
>> [1] "3.14"
>>> format(3.14*c(1, 1e-7), scientific=FALSE)
>> [1] "3.140000000" "0.000000314"
>>>
>>
>> So back to your examples : What would you mean with
>> ``0 significant digits'' ?
>> It really does not make sense to show *no* significant digits ..
>>
>> Intuitively, without spending enough time, I'd say that the bug
>> in format.default() -- which is called by prettyNum() in
>> this case -- is that it does *not* treat
>> 'digits = 0' as 'digits = 1' in this case.
>>
>> NB: digits = 0 has been valid in options(digits = 0) etc,
>> "forever" I think, possibly inherited from S, but I don't
>> really know and I wonder if we should not make it invalid eventually
>> requiring at least 1.
>> So we could make it raise a *warning* (and set it to '1') for now.
>> What do others think?
>>
>> Anyone with S(-PLUS) or Terr or .. who can report if digits=0
>> is allowed there and what it does in a simple situation like
>>
>>> format(as.integer(2^30), digits=0) # digits not used at all
>> [1] "1073741824"
>>> format(2^30, digits=0)
>> [1] "%#4.0-1e"
>>>
>>
>>
>> Last but not least: If you really want to use exponential
>> format, you should typically use sprintf() or formatC() where
>> you can tweak to get what you want.
>>
>> ______________________________________________
>> R-devel using r-project.org mailing list
>> https://stat.ethz.ch/mailman/listinfo/r-devel
> --
> Peter Dalgaard, Professor,
> Center for Statistics, Copenhagen Business School
> Solbjerg Plads 3, 2000 Frederiksberg, Denmark
> Phone: (+45)38153501
> Office: A 4.23
> Email: pd.mes using cbs.dk Priv: PDalgd using gmail.com
More information about the R-devel
mailing list