R gurus,
Every so often(*) someone asks how to suppress scientific notation in
printing, so I thought I'd give it a shot, but I need some help.
The formatting decision is made(**) on line 286 of src/main/format.c :
if (mF <= *m) { /* IFF it needs less space : "F" (Fixpoint)
format */
where mF is the number of characters for "normal" printing and *m is
the number
of characters for scientific notation. If mf <= *m, then parameters are set
that cause "normal" printing. My idea was to introduce a
"penalty" for
scientific notation, which changes line 286 to:
if (mF <= *m + R_print.scipen) {
R_print.scipen is an integer (defaulting to 0) set with "options":
R> options(scipen=99)
I tried to copy the code for R_print.digits (as in
"options(digits=7)")
wherever I found it, notably in the struct "R_print_par_t" defined in
Print.h.
I changed main/options.c and main/print.c, as detailed in the diff output
below. But I must have done it wrong because my version of R crashes with:
> Error: bad value
> Segmentation fault
Can anyone more familiar with options() help? How do you add a new option
parameter? Thanks!
--
-- David Brahm (brahm@alum.mit.edu)
******************************* Footnotes: ***********************************
(*) Thomas Gerds <gerds@fdm.uni-freiburg.de> "[R] printing decimal
numbers"
posted to R-help on 24 Feb 2003.
> how can i force R to print 0.0001 instead of 1e-04???
Bob Porter <rjporter@mindspring.com> "[R] scientific
notation"
posted to R-help on 16 Mar 2003
> Is there a way to force R to forgo use of scientific notation...
(**) In R-1.7.0. Also on lines 395 and 421 for complex numbers.
*********** diff output for my "scipen" modifications to R-1.7.0
*************
diff -r R-1.7.0/src/include/Print.h R-1.7.0.mod/src/include/Print.h
40a41> int scipen;
diff -r R-1.7.0/src/main/format.c R-1.7.0.mod/src/main/format.c
286c286
< if (mF <= *m) { /* IFF it needs less space : "F"
(Fixpoint) format */
---> if (mF <= *m + R_print.scipen) { /* IFF less space : "F"
(Fixpoint) fmt */
395c395
< if (mF <= *mr) { /* IFF it needs less space : "F" (Fixpoint)
format */
---> if (mF <= *mr + R_print.scipen) { /* IFF less space :
"F"(Fixpt) fmt */
421c421
< if (mF <= *mi) { /* IFF it needs less space : "F" (Fixpoint)
format */
---> if (mF <= *mi + R_print.scipen) { /* IFF less space :
"F"(Fixpt) fmt */
diff -r R-1.7.0/src/main/options.c R-1.7.0.mod/src/main/options.c
52a53> * "scipen"
136a138,140> int GetOptionSciPen(SEXP rho) {
> return asInteger(GetOption(install("scipen"), rho));
> }
235a240,243> SET_TAG(v, install("scipen"));
> SETCAR(v, ScalarInteger(0));
> v = CDR(v);
>
374a383,386> else if (streql(CHAR(namei), "scipen")) {
> k = asInteger(argi);
> SET_VECTOR_ELT(value, i, SetOption(tag, ScalarInteger(k)));
> }
diff -r R-1.7.0/src/main/print.c R-1.7.0.mod/src/main/print.c
88a89> R_print.scipen = GetOptionSciPen(rho);
***************************** End diff output ********************************
A couple of hints:
1) You don't need to touch the internal code for options: you can just
set options(scipen=100), or rely on it being unset for the default.
2) I would do something like
R_print.scipen = asInteger(GetOption(install("scipen"), rho));
if(R_print.scipen == NA_INTEGER) R_print.scipen = 0;
Your way you need GetOptionSciPen defined in some common header.
I believe (but have not checked) that if options("scipen") is not
defined
then GetOption(install("scipen"), rho) will be NULL and
asInteger(NULL)
will be NA_INTEGER, but it might well be worth being more cautious.
On Fri, 2 May 2003, David Brahm wrote:
> R gurus,
>
> Every so often(*) someone asks how to suppress scientific notation in
> printing, so I thought I'd give it a shot, but I need some help.
>
> The formatting decision is made(**) on line 286 of src/main/format.c :
>
> if (mF <= *m) { /* IFF it needs less space : "F"
(Fixpoint) format */
>
> where mF is the number of characters for "normal" printing and *m
is the number
> of characters for scientific notation. If mf <= *m, then parameters are
set
> that cause "normal" printing. My idea was to introduce a
"penalty" for
> scientific notation, which changes line 286 to:
>
> if (mF <= *m + R_print.scipen) {
>
> R_print.scipen is an integer (defaulting to 0) set with
"options":
> R> options(scipen=99)
>
> I tried to copy the code for R_print.digits (as in
"options(digits=7)")
> wherever I found it, notably in the struct "R_print_par_t"
defined in Print.h.
> I changed main/options.c and main/print.c, as detailed in the diff output
> below. But I must have done it wrong because my version of R crashes with:
> > Error: bad value
> > Segmentation fault
>
> Can anyone more familiar with options() help? How do you add a new option
> parameter? Thanks!
>
--
Brian D. Ripley, ripley@stats.ox.ac.uk
Professor of Applied Statistics, http://www.stats.ox.ac.uk/~ripley/
University of Oxford, Tel: +44 1865 272861 (self)
1 South Parks Road, +44 1865 272866 (PA)
Oxford OX1 3TG, UK Fax: +44 1865 272595
Big thanks to Prof Brian Ripley <ripley@stats.ox.ac.uk> and Martin
Maechler
<maechler@stat.math.ethz.ch> for help in building a patch to allow
suppression
of scientific notation! The working patch is attached below. Most helpfully,
BDR persuaded me to avoid mucking with the options.c code entirely, so I really
only needed to do three things:
1) Add a component "scipen" to the R_print_par_t struct defined in
Print.h,
2) Set it via GetOption in PrintDefaults, using 0 if the option is undefined,
3) Use it in format.c to penalize the character count for scientific notation.
Normally, R prints "1e+05" rather than "100000" because the
former takes only 5
characters, while the latter takes 6, and 5 < 6. Now if you set
R> options(scipen=3)
R will penalize the scientific notation version by 3 characters, and will print
"100000" in this example because 5+3 >= 6. ("scipen" =
"scientific notation
penalty".) Setting e.g. options(scipen=999) will prevent effectively all
scientific notation.
Note I have not documented the new option, and I have not measured how much
of a performance hit it entails (though I hope the use of PrintDefaults keeps
that low). Anyway, I submit this patch as a possible future enhancement of R.
--
-- David Brahm (brahm@alum.mit.edu)
############################# Patch file follows #############################
#
# Go into the R-1.7.0 directory and type "patch -p1 < scipen.diff"
where
# "scipen.diff" is this file, and "patch" is the GNU patch
utility.
#
diff -cr R-1.7.0/src/include/Print.h R-1.7.0.mod/src/include/Print.h
*** R-1.7.0/src/include/Print.h 2003-01-31 10:00:34.000000000 -0500
--- R-1.7.0.mod/src/include/Print.h 2003-05-05 12:34:56.614703522 -0400
***************
*** 38,43 ****
--- 38,44 ----
int na_width;
int na_width_noquote;
int digits;
+ int scipen;
int gap;
int quote;
int right;
diff -cr R-1.7.0/src/main/format.c R-1.7.0.mod/src/main/format.c
*** R-1.7.0/src/main/format.c 2003-01-24 11:44:50.000000000 -0500
--- R-1.7.0.mod/src/main/format.c 2003-05-05 12:38:51.181370171 -0400
***************
*** 283,289 ****
*n = mxns - 1;
*m = neg + (*n > 0) + *n + 4 + *e; /* width m for E format */
! if (mF <= *m) { /* IFF it needs less space : "F" (Fixpoint)
format */
*e = 0;
*n = rgt;
*m = mF;
--- 283,289 ----
*n = mxns - 1;
*m = neg + (*n > 0) + *n + 4 + *e; /* width m for E format */
! if (mF <= *m + R_print.scipen) { /* Fixpoint if it needs less space */
*e = 0;
*n = rgt;
*m = mF;
***************
*** 392,398 ****
else *er = 1;
*nr = mxns - 1;
*mr = neg + (*nr > 0) + *nr + 4 + *er;
! if (mF <= *mr) { /* IFF it needs less space : "F" (Fixpoint)
format */
*er = 0;
*nr = rt;
*mr = mF;
--- 392,398 ----
else *er = 1;
*nr = mxns - 1;
*mr = neg + (*nr > 0) + *nr + 4 + *er;
! if (mF <= *mr + R_print.scipen) { /* Fixpoint if it needs less
space */
*er = 0;
*nr = rt;
*mr = mF;
***************
*** 418,424 ****
else *ei = 1;
*ni = i_mxns - 1;
*mi = (*ni > 0) + *ni + 4 + *ei;
! if (mF <= *mi) { /* IFF it needs less space : "F" (Fixpoint)
format */
*ei = 0;
*ni = i_rt;
*mi = mF;
--- 418,424 ----
else *ei = 1;
*ni = i_mxns - 1;
*mi = (*ni > 0) + *ni + 4 + *ei;
! if (mF <= *mi + R_print.scipen) { /* Fixpoint if it needs less
space */
*ei = 0;
*ni = i_rt;
*mi = mF;
diff -cr R-1.7.0/src/main/print.c R-1.7.0.mod/src/main/print.c
*** R-1.7.0/src/main/print.c 2003-03-04 05:51:24.000000000 -0500
--- R-1.7.0.mod/src/main/print.c 2003-05-05 12:37:06.998036850 -0400
***************
*** 86,91 ****
--- 86,93 ----
R_print.quote = 1;
R_print.right = 0;
R_print.digits = GetOptionDigits(rho);
+ R_print.scipen = asInteger(GetOption(install("scipen"), rho));
+ if (R_print.scipen == NA_INTEGER) R_print.scipen = 0;
R_print.gap = 1;
R_print.width = GetOptionWidth(rho);
}
#
############################# End of patch file #############################