Function to validate a CPF in R

Asked

Viewed 1,169 times

-6

Please, I need a function in R to validate a CPF, i.e., check if a number passed as a parameter is a valid CPF.

  • 3

    And what you’ve done?

  • 2

    What would be the criteria for the number to be a valid CPF?

  • Where’s the code where you’re having doubts

1 answer

9

Well, since no one answered, although I agree with the above comments, today is Sunday, here it goes.
First of all, you could have actually included some information about this CPF. Read Rafael Cunha’s comment again. I who am Portuguese had never even heard of such a thing. In Wikipedia I have found all the necessary information including the algorithm which I will use below. This should have been your job.

Code.
The code below are three functions. The first, cpf_dig_controle computes the control digits or checkers of an 8-digit number. The function is vectored so as to accept numerical vectors as input. If by any chance the entrance is class character the function in principle also does not choke but I do not guarantee this.

cpf_dig_controle <- function(y){
    v1 <- 0L
    v2 <- 0L
    z <- as.integer(rev(strsplit(as.character(y), "")[[1]]))
    for(i in seq_along(z)){
        v1 <- v1 + z[i]*(9 - (i %% 10))
        v2 <- v2 + z[i]*(9 - ((i + 1) %% 10))
    }
    v1 <- (v1 %% 11) %% 10
    v2 <- v2 + v1*9
    v2 <- (v2 %% 11) %% 10
    c(v1, v2)
}

Next come two functions, one to generate CPF numbers, with the proper formatting and another to check its validity.

cpf_gerar <- function(x){
    g <- function(y, v){
        z <- strsplit(as.character(y), "")[[1]]
        z <- as.integer(c(z, v))
        res <- sprintf(fmt = "%d%d%d.%d%d%d.%d%d%d-%02d",
                             z[1], z[2], z[3], z[4], z[5],
                             z[6], z[7], z[8], z[9], z[10])
        res
    }
    v <- lapply(x, cpf_dig_controle)
    result <- sapply(seq_along(x), function(i) g(x[i], v[[i]]))
    result
}

cpf_validar <- function(x){
    f <- function(y){
        z <- unlist(strsplit(y, "\\."))
        v <- substr(z[3], 3, 6)
        v <- as.integer(unlist(strsplit(v, "-")))
        z[3] <- substr(z[3], 1, 2)
        z <- as.integer(paste(z, collapse = ""))
        list(x = z, v = v)
    }
    result <- lapply(x, f)
    valido <- lapply(result, function(r) unlist(lapply(r$x, cpf_dig_controle)))
    valido <- sapply(seq_along(valido), function(i)
                    result[[i]]$v[1] == valido[[i]][1] & result[[i]]$v[2] == valido[[i]][2]
                )
    valido
}

cpf <- cpf_gerar(c(12345678, 87654321))
cpf
#[1] "123.456.786-02" "876.543.210-07"

cpf_validar(cpf)
#[1] TRUE TRUE

cpf_validar(c("123.456.786-02", "876.543.211-07"))
#[1]  TRUE FALSE

Browser other questions tagged

You are not signed in. Login or sign up in order to post.