This is a discussion forum, Richard, and I welcome requests to clarify what I
wrote or to be corrected, especially when my words have been read with an
attempt to understand. I do get private responses too and some days i wonder if
I am not communicating the way people like!
But let me repeat. The question we started with asked about R. My answer applies
to quite a few languages besides R and maybe just about all of them.
I got private email insisting the numbers being added were not irrational so why
would they not be represented easily as a sum. I know my answers included parts
at various levels of abstraction as well as examples of cases when Decimals
notation for a number like 1/7 results in an infinite repeating sequence. So, I
think it wise to follow up with what binary looks like and why hardly ANYTHING
that looks reasonable is hard to represent exactly.
Consider that binary means POWERS OF TWO. The sequence 1101 before a decimal
point means (starting from the right and heading left) that you have one ONES
and no TWOS and one FOURS and one EIGHTS. Powers of two ranging from 2 to the
zero power to two cubed. You can make any integer whatsoever using as long a
sequence of zeros and ones as you like. Compare this to decimal notation where
you use powers of ten and of course can use any of 0-9.
But looking at fractional numbers, like 1/7 and 1/10, it gets hard and inexact.
Remember now we are in BINARY. Here are some fractions with everything not shown
to the right being zeros and thus not needed to be shown explicitly. Starting
with the decimal point, read this from left to right to see the powers in the
denominator rising so 1/2 then 1/4 then 1/8 ...:
0.0 would be 0.
0.1 would be 1/2
0.101 would be 1/2 + 1/8 or 5/8
0.11 would be 1/2 + 1/4 or 3/4
0.111 would be 1/2 + 1/4 + 1/8 or 7/8
We are now using negative powers where 2 raised to the minus one power is one
over two raised to the plus one power, or 1/2 and so on. As you head to the
right you get to fairly small numbers like 1/2048 ...
Every single binary fraction is thus a possibly infinite sum of negative powers
of two, or rather the reciprocals of those in positive terms.
If you want to make 1/7, to some number of decimal places, it looks like this up
to some point where I stop:
0.00100100100100100101
So no halves, no quarters, 1/8, no sixteenths, no thirty-seconds, 1/64, and so
on. But if you add all that up, and note the sequence was STOPPED before it
could continue further, you get this translated into decimal:
0.142857 55157470703125
Recall 1/7 in decimal notation is
0.142857 142857142857142857...
Note the divergence at the seventh digit after the decimal point. I left a space
to show where they diverge. If I used more binary digits, I can get as close as
I want but computers these days do not allow too many more digits unless you use
highly specialized programs. There are packages that give you access such as
"mpfr" but generally nothing can give you infinite precision. R will
not handle an infinite number of infinitesimals.
The original problem that began our thread was about numbers like 0.1 and 0.2
and so on. In base ten, they look nice but I repeat in base 2 only powers of TWO
reign.
0.1 in base two is about 0.0001100110011001101
that reads as 1/16 + 1/32 + 1/256 + 1/512 + ...
If I convert the above segment, which I repeat was stopped short, I get
0.1000003814697265625 which is a tad over and had I taken the last 1 and changed
it to a zero as in 0.0001100110011001100 then we would have a bit under at
0.09999847412109375
So the only way to write 0.1 exactly is to continue infinitely, again. Do the
analysis and understand why most rational numbers will not easily convert to a
small number of bits. But the advantages of computers doing operations in binary
are huge and need not be explained. You may THINK you are entering numbers in
decimal form but they rarely remain that way for long before they simply become
binary and often remain binary unless and until you ask to print them out,
usually in decimal.
BTW, I used a random web site to do the above conversion calculations:
https://www.rapidtables.com/convert/number/binary-to-decimal.html
Since I am writing in plain text, I cannot show what it says in the box on that
page further down under Decimal Calculation Steps so I wonder what the rest of
this message looks like:
(0.0001100110011001100)? = (0 ? 2?) + (0 ? 2??) + (0 ? 2??) + (0 ? 2??) + (1 ?
2??) + (1 ? 2??) + (0 ? 2??) + (0 ? 2??) + (1 ? 2??) + (1 ? 2??) + (0 ? 2???) +
(0 ? 2???) + (1 ? 2???) + (1 ? 2???) + (0 ? 2???) + (0 ? 2???) + (1 ? 2???) + (1
? 2???) + (0 ? 2???) + (0 ? 2???) = (0.09999847412109375)??
I think my part in this particular discussion can now finally come to an end. R
and everything else can be incomplete. Deal with it!
-----Original Message-----
From: Richard M. Heiberger <rmh at temple.edu>
To: Avi Gross <avigross at verizon.net>
Cc: nboeger at gmail.com <nboeger at gmail.com>; r-help at r-project.org
<r-help at r-project.org>
Sent: Tue, Feb 1, 2022 9:04 pm
Subject: Re: [External] [R] Funky calculations
I apologize if my tone came across wrong.? I enjoy reading your comments on this
list.
My goal was to describe what the IEEE and R interpret "careful coding"
to be.
> On Feb 01, 2022, at 20:42, Avi Gross <avigross at verizon.net> wrote:
>
> Richard,
>
> I think it was fairly clear I was explaining how people do arithmetic
manually and often truncate or round to some number of decimal places. I said
nothing about what R does or what the IEEE standards say and I do not
particularly care when making MY point.
>
> My point is that humans before computers also had trouble writing down any
decimals that continue indefinitely. It cannot be expected computer versions of
arithmetic can do much better. Different people can opt to do the calculation
with the same or different numbers of digits ad when compared to each other they
may not match.
>
> I do care what it does in my programs, of course. My goal here was to
explain to someone that the anomaly found was not really an anomaly and that
careful coding may be required in these situations.
>
>
> -----Original Message-----
> From: Richard M. Heiberger <rmh at temple.edu>
> To: Avi Gross <avigross at verizon.net>
> Cc: Nathan Boeger <nboeger at gmail.com>; r-help at r-project.org
<r-help at r-project.org>
> Sent: Tue, Feb 1, 2022 2:44 pm
> Subject: Re: [External] [R] Funky calculations
>
>
> RShowDoc('FAQ')
>
>
> then search for 7.31
>
>
> This statement
> "If you stop at a 5 or 7 or 8 and back up to the previous digit, you
round up. Else you leave the previous result alone."
> is not quite right.? The recommendation in IEEE 754, and this is how R does
arithmetic, is to Round Even.
>
> I ilustrate here with decimal, even though R and other programs use binary.
>
>> x <- c(1.4, 1.5, 1.6, 2.4, 2.5, 2.6, 3.4, 3.5, 3.6, 4.4, 4.5, 4.6)
>> r <- round(x)
>> cbind(x, r)
>? ? ? ? x r
> [1,] 1.4 1
> [2,] 1.5 2
> [3,] 1.6 2
> [4,] 2.4 2
> [5,] 2.5 2
> [6,] 2.6 3
> [7,] 3.4 3
> [8,] 3.5 4
> [9,] 3.6 4
> [10,] 4.4 4
> [11,] 4.5 4
> [12,] 4.6 5
>>
>
> Numbers whose last digit is not 5 (when in decimal) round to the nearest
integer.
> Numbers who last digit is 5 (1.5, 2.5, 3.5, 4.5 above)
> round to the nearest EVEN integer.
> Hence 1.5 and 3.5 round up to the even numbers 2 and 4.
> 2.5 and 4.5 round down do the even numbers 2 and 4.
>
> This way the round ups and downs average out to 0.? If we always went up
from .5 we would have
> an updrift over time.
>
> For even more detail click on the link in FAQ 7.31 to my appendix
> https:// link.springer.com/content/pdf/bbm%3A978-1-4939-2122-5%2F1.pdf
> and search for "Appendix G".
>
> Section G.5 explains Round to Even.
> Sections G.6 onward illustrate specific examples, such as the one that
started this email thread.
>
> Rich
>