Bug 16752 - deparse, str and toString are incorrect for complex number with exponent
Summary: deparse, str and toString are incorrect for complex number with exponent
Alias: None
Product: R
Classification: Unclassified
Component: Accuracy (show other bugs)
Version: R-devel (trunk)
Hardware: All All
: P5 minor
Assignee: R-core
Depends on:
Reported: 2016-03-07 22:36 UTC by Pavel Minaev
Modified: 2016-03-11 07:59 UTC (History)
2 users (show)

See Also:


Note You need to log in before you can comment on or make changes to this bug.
Description Pavel Minaev 2016-03-07 22:36:03 UTC
> c <- -4.2e+10 + 2.4e-10i
> c
[1] -4.2e+10+0e+00i
> deparse(c)
[1] "-4.2e+10+0e+00i"
> str(c)
 cplx -4.2e+10+0e+00i
> toString(c)
[1] "-4.2e+10+0e+00i"
> c1 <- eval(parse(text = deparse(c)))
> c1
[1] -4.2e+10+0i
> c == c1
Comment 1 Pavel Minaev 2016-03-07 22:37:41 UTC
Note that the actual components of the number are correct, it's only string representation that is broken:

> Im(c)
[1] 2.4e-10
> Re(c)
[1] -4.2e+10
Comment 2 Duncan Murdoch 2016-03-09 00:47:57 UTC
The default display rounds complex values according to options('digits'), where the larger of Im(x) and Re(x) determines the scale.  If you want something closer to a faithful display of values where the scales differ, you'll need to use deparse(x, control = "digits17").
Comment 3 Pavel Minaev 2016-03-09 00:56:53 UTC
I've tried "digits17", but that produces undesirable whitespace padding in the same scenario:

> deparse(c, control = "digits17")
[1] "-42000000000 +           2.4e-10i"

Ideally, I'd also like for the output to prefer the exponent notation if it's shorter (as %g usually does), rather than having it try to actually spell it out in full - i.e. as close to the original input as possible.

Is there any way to do so with deparse function family, without special-casing complex?
Comment 4 Martin Maechler 2016-03-11 07:38:02 UTC
As Duncan says this is "by design" (from Aug.2005) and is also documented ... though that documentation is in  ?round  (base/man/Round.Rd)  and hence pretty hidden when you search the help pages  ?deparse, ?print, ?format, ?as.character.

I'd accept it as both "documentation bug" and "wishlist",  the latter because I do believe we can do better.  This indeed is only P5 priority.
Comment 5 Pavel Minaev 2016-03-11 07:59:10 UTC
Let me clarify what I'm actually trying to do here - perhaps there's an altogether different and better way to achieve that.

I'm a developer working on RTVS (R Tools for Visual Studio). As part of that, we've implemented a debugger, including support for the IDE Locals tool window, that displays local variables with their values and types for a given stack frame / environment.

Variable values are meant to be editable, and so, in general, language plugins in VS use the same representation for values in Locals as the syntax of the language itself, and where there's no literal for that value, use the best available parseable representation - such that, when the user edits the value, the edited representation can be re-evaluated and assigned. 

The secondary consideration is that the value should also have the most compact representation possible, because it is displayed in a small window with many other values, so information density is important.

For Python, for example, this representation is provided by repr().

For R, our assumption, based on the documentation, has been that deparse() is the best candidate. It does seem to work really well in most cases - obviously, it's not always 100% round-trippable, nor does it guarantee to be - but for pretty much all basic types, and even many aggregates, it works great in practice. Except for this particular corner case, where the default behavior is not round-trippable (and so user is limited in their ability to edit the value); and using "digits17" results in a significantly longer representation, even though the shorter exponential form would be just as accurate.

Did we go wrong with using deparse() for this purpose? Or is it just a special case that needs to be handled as such?