[R] strangely long floating point with write.table()

peter dalgaard pdalgd at gmail.com
Sat Mar 15 22:41:38 CET 2014


On 15 Mar 2014, at 20:54 , Mike Miller <mbmiller+l at gmail.com> wrote:

> On Sat, 15 Mar 2014, peter dalgaard wrote:
> 
>> I don't think so. I think some of your numbers differ sufficiently from numbers with only a few digits to the right of the decimal that write.table needs to write them with increased precision. You didn't read them like that, didn't you? You did some calculations, and then it _looked like_ the results have <= 6 digits after the decimal point?
> 
> These have different representations:
> 
> 1-0.995
> 2-1.995
> 
> write(c(1-0.995, 2-1.995), file="data1.txt", sep="\n")
> write.table(c(1-0.995, 2-1.995), file="data2.txt", row.names=F, col.names=F)
> 
> $ head -2 data[12].txt
> ==> data1.txt <==
> 0.005
> 0.005
> 
> ==> data2.txt <==
> 0.005
> 0.00499999999999989
> 
> 
>> The digits= setting has nothing to do with this, write.table alway does its damndest to avoid loss of precision. This _is_ in help(write.table):
>> 
>>    In almost all cases the conversion of numeric quantities is
>>    governed by the option ‘"scipen"’ (see ‘options’), but with the
>>    internal equivalent of ‘digits = 15’.  For finer control, use
>>    ‘format’ to make a character matrix/data frame, and call
>>    ‘write.table’ on that.
> 
> Yes!  This was my mistake:  write() not write.table() is controlled by options(digits=7).  Repeating the write() command using a different number of digits:
> 
>> options(digits=15)
>> getOption("digits")
> [1] 15
>> write(c(1-0.995, 2-1.995), file="data1.txt", sep="\n")
> 
> $ cat data1.txt
> 0.005
> 0.00499999999999989
> 
> I don't know why it shows 17 digits and doesn't round to 15, but it is showing that the numbers are different, for some reason.
> 

Aiding my weakening eyesight a little:

0.004 999 999 999 999 89

Notice that that makes 15 _significant_ digits.

> Do you understand why there is a difference between 1-0.995 and 2-1.995 in their internal representations?

Let's see,  that'll be like 

1 - 2/3 vs. 10 - 29/3 

on a decimal computer if someone is perverse enough to give input in base 3 (i.e., 1.0 - 0.2 ternary vs. 101.0 - 100.2 ternary). Assume that the computer is floating point with 3 significant digits (and possibly taking some liberties compared to what real computers really do), we have

   1 = 1.000 * 10^0
  10 = 1.000 * 10^1
 2/3 = 0.667 * 10^0
29/3 = 0.967 * 10^1 

 1 - 2/3  = 0.333 * 10^0
10 - 29/3 = 0.033 * 10^1 = 0.330 * 10^0

So, yes, I think I do understand how these things can happen.

-pd

> 
> Mike

-- 
Peter Dalgaard, Professor,
Center for Statistics, Copenhagen Business School
Solbjerg Plads 3, 2000 Frederiksberg, Denmark
Phone: (+45)38153501
Email: pd.mes at cbs.dk  Priv: PDalgd at gmail.com




More information about the R-help mailing list