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 #############################