[R] [External] Funky calculations

Nathan Boeger nboeger @end|ng |rom gm@||@com
Thu Feb 3 03:14:01 CET 2022


You have a typo:

   printf("0.4+0.4+0.4+0.4 == 1.6 -> %s\n", d == 1.0 ? "true" : "false");

should be:

   printf("0.4+0.4+0.4+0.4 == 1.6 -> %s\n", d == 1.6 ? "true" : "false");

The comparison was with 1.0 but should be 1.6. I ran it and it has the same
output as you show above. Very interesting.

-nb

On Wed, 2 Feb 2022 at 21:24, Bill Dunlap <williamwdunlap using gmail.com> wrote:

> Floats have 23 bits of precision so the rounding is done there instead of
> at 52 bits, hence a different example is needed to show the problem with
> floats.
>
> bill using Bill-T490:~$ cat b.c
> #include <stdio.h>
>
> int main(int argc, char* argv[])
> {
>     float d = 0.4 + 0.4 + 0.4 + 0.4;
>     printf("0.4+0.4+0.4+0.4 -> %24.17g\n", (double)d);
>     printf("0.4+0.4+0.4+0.4 == 1.6 -> %s\n", d == 1.0 ? "true" : "false");
>     return 0;
> }
> bill using Bill-T490:~$ gcc b.c
> bill using Bill-T490:~$ ./a.out
> 0.4+0.4+0.4+0.4 ->       1.6000000238418579
> 0.4+0.4+0.4+0.4 == 1.6 -> false
>
> There is no getting around the fact that rounding will happen.
>
> -Bill
>
> On Tue, Feb 1, 2022 at 9:06 PM Nathan Boeger <nboeger using gmail.com> wrote:
>
>>
>> I understand this and with C the data type used is important. For this
>> type of calculation, I would normally use a float (basic single precision
>> is all I require).
>>
>> #include <stdio.h>
>>
>> void main() {
>>   float foo = (0.4 + 0.2 + 0.30 + 0.1) ;
>>   printf("foo: %f , foo > 1: %s \n", foo, (foo > 1.0 ? "true" : "false"));
>>   double bar = (0.4 + 0.2 + 0.30 + 0.1) ;
>>   printf("bar: %lf , bar > 1: %s \n", bar, (bar > 1.0 ? "true" :
>> "false"));
>> }
>>
>> gcc  c-check.c -o c-check
>> ./c-check
>> foo: 1.000000 , foo > 1: false
>> bar: 1.000000 , bar > 1: true
>>
>> Again, it was my mistake for not reading the R-FAQ. I had no idea it
>> would spark such a long thread.
>>
>> Cheers
>>
>> -nb
>>
>> On Wed, 2 Feb 2022 at 10:30, Bill Dunlap <williamwdunlap using gmail.com>
>> wrote:
>>
>>> The base 2 representation of 0.4 repeats the digit sequence 1001
>>> infinitely, hence must be rounded.  The problem occurs in C the same as it
>>> does in R.
>>>
>>> bill using Bill-T490:~$ cat a.c
>>> #include <stdio.h>
>>>
>>> int main(int argc, char* argv[])
>>> {
>>>     double d = 0.4 + 0.3 + 0.2 + 0.1;
>>>     printf("0.4+0.3+0.2+0.1 -> %24.17g\n", d);
>>>     printf("0.4+0.3+0.2+0.1 == 1.0 -> %s\n", d == 1.0 ? "true" :
>>> "false");
>>>     return 0;
>>> }
>>> bill using Bill-T490:~$ gcc a.c
>>> bill using Bill-T490:~$ ./a.out
>>> 0.4+0.3+0.2+0.1 ->      0.99999999999999989
>>> 0.4+0.3+0.2+0.1 == 1.0 -> false
>>>
>>> -Bill
>>>
>>> On Tue, Feb 1, 2022 at 7:01 PM Nathan Boeger <nboeger using gmail.com> wrote:
>>>
>>>> Thank you for this explanation!
>>>>
>>>> I have a long background in C/C++ and never realized this was such an
>>>> issue
>>>> with some languages. At least, with trivial single digit decimals. I
>>>> understand accuracy issues with very large decimals, repeating or
>>>> non-terminating rationals and I have handled them in the past. It makes
>>>> me
>>>> worried about all the R scripts I have written before (yikes!).
>>>>
>>>> Cheers
>>>>
>>>> -nb
>>>>
>>>> On Wed, 2 Feb 2022 at 02:44, Richard M. Heiberger <rmh using temple.edu>
>>>> wrote:
>>>>
>>>> > 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
>>>>
>>>>         [[alternative HTML version deleted]]
>>>>
>>>> ______________________________________________
>>>> R-help using r-project.org mailing list -- To UNSUBSCRIBE and more, see
>>>> https://stat.ethz.ch/mailman/listinfo/r-help
>>>> PLEASE do read the posting guide
>>>> http://www.R-project.org/posting-guide.html
>>>> and provide commented, minimal, self-contained, reproducible code.
>>>>
>>>

	[[alternative HTML version deleted]]



More information about the R-help mailing list