1

The function follows:

qual <- function(x, y, z)
{if ((abs(x - y) <= .15)&(abs(x - z) <= .15)&(abs(y - z) <= .15)){print("grade A")} 
else if((abs(x - y) <= .15)|(abs(x - z) <= .15)){print("grade B")} 
else if((abs(x - y) <= .2)|(abs(x - z) <= .2)){print("grade C")} 
else if((abs(x - y) <= .25)|(abs(x - z) <= .25)){print("grade D")} 
else {print("check manually")}}

It seems that, e.g., the output of qual(1.19, 1.04, 1.06) and qual(1.10, .95, .97)should be "grade A". However, the output is "grade A" and "grade B", respectively.

Why is this?

Bill W.
  • 13
  • 2
  • I think you are running into floating point precision errors, look at `abs(1.10 - 0.95) <= 0.15`. – Marius Jul 18 '18 at 03:53
  • @Marius I'm pretty sure that's it, that difference should be `0.15000000000000013` or so. – Amadan Jul 18 '18 at 03:54

1 Answers1

0

I think you are hitting some floating point precision problems. See Why are these numbers not equal for a full explanation.

To fix this, you can use a short function that takes into account minor precision errors when comparing:

less_equal_safe <- function(x, y) {
    (x < y) | dplyr::near(x, y)
}

qual <- function(x, y, z) {
    if (less_equal_safe(abs(x - y), .15) & (abs(x - z) <= .15) &(abs(y - z) <= .15)) {
        print("grade A")
    } else if ((abs(x - y) <= .15) | (abs(x - z) <= .15)) {
        print("grade B")
    } else if ((abs(x - y) <= .2) | (abs(x - z) <= .2)) {
        print("grade C")
    } 
    else if ((abs(x - y) <= .25) | (abs(x - z) <= .25)) {
        print("grade D")
    } else {
        print("check manually")
    }
}

(note that you need the dplyr package to be installed to use dplyr::near)

I've only replaced the first comparison, which is the one that was causing the issue, but ideally you should replace all comparisons in your function with the float-safe function.

Marius
  • 58,213
  • 16
  • 107
  • 105