r4ds-exercise-solutions icon indicating copy to clipboard operation
r4ds-exercise-solutions copied to clipboard

Typo in the Exercise 20.3.4

Open AnttiRask opened this issue 1 year ago • 0 comments

https://jrnold.github.io/r4ds-exercise-solutions/vectors.html#exercise-20.3.4

I was testing this function (see code below) and there is a problem with the "nearest, round half to odd" case_when part:

case_when(
      # smaller integer is odd - round half down
      floor(x) %% 2 ~ ceiling(x - 0.5),
      # otherwise, round half up 
      TRUE ~ floor(x + 0.5)

This is the error message I receive:

"Error in case_when(): ! LHS of case 1 (floor(x)%%2) must be a logical vector, not a double vector. Run rlang::last_error() to see where the error occurred. Called from: signal_abort(cnd, .file)"

And I'm pretty sure that this is how that particular case_when() should look like:

case_when(
      # smaller integer is odd - round half down
      floor(x) %% 2 != 0 ~ ceiling(x - 0.5),
      # otherwise, round half up 
      TRUE ~ floor(x + 0.5)
    )

This is the whole function (before changes):

function(x, method) {
  if (method == "round down") {
    floor(x)
  } else if (method == "round up") {
    ceiling(x)
  } else if (method == "round towards zero") {
    trunc(x)
  } else if (method == "round away from zero") {
    sign(x) * ceiling(abs(x))
  } else if (method == "nearest, round half up") {
    floor(x + 0.5)
  } else if (method == "nearest, round half down") {
    ceiling(x - 0.5)
  } else if (method == "nearest, round half towards zero") {
    sign(x) * ceiling(abs(x) - 0.5)
  } else if (method == "nearest, round half away from zero") {
    sign(x) * floor(abs(x) + 0.5)
  } else if (method == "nearest, round half to even") {
    round(x, digits = 0)
  } else if (method == "nearest, round half to odd") {
    case_when(
      # smaller integer is odd - round half down
      floor(x) %% 2 ~ ceiling(x - 0.5),
      # otherwise, round half up 
      TRUE ~ floor(x + 0.5)
    )
  } else if (method == "nearest, round half randomly") {
    round_half_up <- sample(c(TRUE, FALSE), length(x), replace = TRUE)
    y <- x
    y[round_half_up] <- ceiling(x[round_half_up] - 0.5)
    y[!round_half_up] <- floor(x[!round_half_up] + 0.5)
    y
  }
}

And after:

function(x, method) {
  if (method == "round down") {
    floor(x)
  } else if (method == "round up") {
    ceiling(x)
  } else if (method == "round towards zero") {
    trunc(x)
  } else if (method == "round away from zero") {
    sign(x) * ceiling(abs(x))
  } else if (method == "nearest, round half up") {
    floor(x + 0.5)
  } else if (method == "nearest, round half down") {
    ceiling(x - 0.5)
  } else if (method == "nearest, round half towards zero") {
    sign(x) * ceiling(abs(x) - 0.5)
  } else if (method == "nearest, round half away from zero") {
    sign(x) * floor(abs(x) + 0.5)
  } else if (method == "nearest, round half to even") {
    round(x, digits = 0)
  } else if (method == "nearest, round half to odd") {
    case_when(
      # smaller integer is odd - round half down
      floor(x) %% 2 != 0 ~ ceiling(x - 0.5),
      # otherwise, round half up 
      TRUE ~ floor(x + 0.5)
    )
  } else if (method == "nearest, round half randomly") {
    round_half_up <- sample(c(TRUE, FALSE), length(x), replace = TRUE)
    y <- x
    y[round_half_up] <- ceiling(x[round_half_up] - 0.5)
    y[!round_half_up] <- floor(x[!round_half_up] + 0.5)
    y
  }
}

AnttiRask avatar Jul 24 '22 14:07 AnttiRask