5

So I am quite new to R, and I am reading the book R for Data Science(2e).

I reproduced the code shown below from the book and it returned a different output. I'm not sure why

code from the book

x <- c(1 / 49 * 49, sqrt(2) ^ 2)
x
#> [1] 1 2

print(x, digits = 16)
#> [1] 0.9999999999999999 2.0000000000000004

my code

print(sqrt(2)^2, digits = 16)
#[1] 2

#then tried saving it to an object, same output
sq_2 <- sqrt(2)^2
print(sq_2, digits = 16)
#[1] 2

I also tried saving it as a vector (single item), same output

NB: the problem is the different approximation from similar code.

1

2 Answers 2

5

It's affected by the other entry (1 / 49 * 49) which shows 0.9999999999999999 (16 decimal places) when printed with digits = 16, so every value in x is displayed with 16 decimal places.

You can get 2.0000000000000004 (1 integer place + 16 decimal places) using print(sq_2, digits = 17).

If you print(sq_2, digits = 16), it tries to show 1 integer place + 15 decimal places, but then all 15 decimal places are 0, so it just prints "2".


If you try x <- c( sqrt(2) ^ 2, 1 / 49* 49 , 12.01) and print(x, digits = 16), the 12.01 will become 12.0099999999999998 which is also with 16 decimal places.

However, to print 12.01 (by itself) as 12.0099999999999998, you need print(12.01, digits = 18) (here I use 18 because of 2 integer places + 16 decimal places)


We can also observe a similar phenomenon with a simpler example:
print(c(0.21, 2.31), digits=2) printing 0.21 2.31,
print(c(2.31), digits=2) printing 2.3 (not 2.31)

The number of decimal places displayed is affected by the other elements of the vector.


EDIT
Another test:
print(c(21.000005, 4.0000002, 0.3402), digits=3) printing 21.00 4.00 0.34

What happened seems to be like this:
21.00005 (digits=3, so 2 integer places + 1 decimal place)
4.0000002 (digits=3, so 1 integer place + 2 decimal places)
0.3402 (digits=3, so 3 decimal places)
The maximum number of decimal places is 3, so round it to "21.000 4.000 0.340". However, the 3rd decimal place of every number is 0, it drops the 3rd decimal place, resulting in 21.00 4.00 0.34

Sign up to request clarification or add additional context in comments.

2 Comments

thanks, following your response, I read the documentation on the print function and the argument digits defines the number of significant digits to be displayed in the output. I guess R switches to decimal places after evaluating the first item.
@blessingAlabi If there is only one item to display, R uses significant digits. So "16 significant figures" can be "0 integer places + 16 decimal places", "1 integer place + 15 decimal places" or "2 integer places + 14 decimal places" etc depending on the number. However, if there are 2 or more items, the max number of decimal places (not always from the first number) would be the chosen.
3

What you are observing is R battling with the IEEE 754 standard for floating point arithmetic. Note that sqrt(2)^2 is not actually 2:

> print(sqrt(2)^2, digits = 16)
[1] 2
> print(sqrt(2)^2, digits = 18)
[1] 2.00000000000000044
> 

Similarly, 1/49*49 is not 1:

> print(1/49*49, digits = 16)
[1] 0.9999999999999999
> 

As you are showing, when you put these together in a vector, they are also not equal to c(1, 2). Why print(sqrt(2)^2, digits = 16) rounds to 2 when print(c(1/49*49, sqrt(2)^2), digits = 16) doesn't is somewhat of a mystery.

If you want to read a little more about floating point imprecision, this website is a good reference.

1 Comment

thanks for sharing the link on floating point precision

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.