O uso de R em cálculos de precisão

Periodicamente, existem problemas, mesmo na vida cotidiana, quando a precisão dos bits float64/ int64não é suficiente para obter uma resposta com a precisão necessária. Correndo em busca de outro instrumento? Também é uma opção.


Ou você não pode fazer isso, mas fique curioso e descubra que, para calcular com precisão arbitrária, a biblioteca GNU MPFR foi criada há muito tempo para a qual existem wrappers para quase todos os idiomas. A prática mostra que poucas pessoas estão familiarizadas com esta biblioteca, o que provavelmente é causado pelas peculiaridades dos programas de estudo nas universidades e pelo subsequente mainstream do programador.


A biblioteca é boa e merece atenção, pelo menos no âmbito de ampliar seus horizontes. Em R, há um wrapper Rmpfr . Abaixo, darei um exemplo simples de problemas para crianças em idade escolar (bem, não toque nos dados do projeto sob a NDA) e abordarei vários rakes clássicos que são atacados quase imediatamente.


É uma continuação de publicações anteriores .


Por exemplo, considere o problema nº 39 da competição do ano letivo de 2019/2020 no Quantum: Os
números positivos x e y são tais que na desigualdade abaixo da fração esquerda é maior que a direita. Qual é maior: x ou y?


frações de cadeia


Naturalmente, ele deve ser resolvido analiticamente (alternando a desigualdade), mas esse não é um motivo para não usá-lo como demonstração.


Desenhamos um código simples para calcular a sequência de frações. Você pode definir imediatamente o valor final, mas depois o demoscene para mpfr, então avançamos em pequenas etapas.


Resolvemos por métodos padrão
library(tidyverse)
library(magrittr)
options(digits=15)

frec <- function(stopval, n, x){
  res <- ifelse(n == stopval, 
                (stopval - 1) + stopval/(stopval + 1 + x), 
                (n - 1 ) + n / (frec(stopval, n + 2, x))
  )
  res
}

frec_wrap <- function(stopval, x){
  res <- frec(stopval = stopval, n = 1, x = x)
  print(glue::glue("{stopval}: {res}"))
  res
}

sol_df <- tibble(stopval = seq(1, 29, by = 2)) %>%
  mutate(val1 = purrr::map_dbl(stopval, frec_wrap, x = 1),
         val2 = purrr::map_dbl(stopval, frec_wrap, x = 5),
         delta = val1 - val2)

E aqui está uma má sorte, já na 14ª iteração (número de parada = 29), a precisão não é suficiente para distinguirmos entre frações. E você deve considerar até 2019!


Falha 1


? , Rmfpr. — float64 mpfr .


library(tidyverse)
library(magrittr)
library(Rmpfr)
frec2 <- function(stopval, n, x){
  if(n == stopval){
    (stopval - 1) + stopval/(stopval + 1 + x)} else {
      (n - 1 ) + n / (frec2(stopval, n + 2, x))
    }
}
frec2_wrap <- function(stopval, x){
  .precision <- 5000
  res <- frec2(stopval = mpfr(stopval, .precision), 
               n = mpfr(1, .precision), 
               x = mpfr(x, .precision)
  )
  print(glue::glue("{stopval}: {formatMpfr(res, drop0trailing = TRUE)}"))
  res
}

sol2_df <- tibble(stopval = seq(1, 29, by = 2)) %>%
  mutate(val1 = purrr::map(stopval, frec2_wrap, x = 1),
         val2 = purrr::map(stopval, frec2_wrap, x = 5))

. , tibble . .


Falha 2


№1:
tibble , vctrs. ( mpfr S4 ) list-column. - .
, vctrs . , :


for(jj in 1:12){
  #   ,       
  flags_df[[glue("bp_2_{jj}_T")]] <- flags_df[[glue("bp_2_{jj}_in")]] &   flags_df[[glue("flag_2_{jj}")]]
  flags_df[[glue("bp_2_{jj}_F")]] <- flags_df[[glue("bp_2_{jj}_in")]] & ! flags_df[[glue("flag_2_{jj}")]]
}

№2:
list-column . mpfr list-column.


№3
rpfm . StackOverflow . . R?


? --! R, Python! !
. RTFM, .


  • №1. — tibble . data.frame.
  • №2. rpfm . , . data.frame .
  • №3. formatMpfr .

.


library(tidyverse)
library(magrittr)
library(Rmpfr)
#    
frec2 <- function(stopval, n, x){
  if(n == stopval){
    (stopval - 1) + stopval/(stopval + 1 + x)} else {
      (n - 1 ) + n / (frec2(stopval, n + 2, x))
    }
}
frec2_wrap <- function(stopval, x){
  # browser()
  .precision <- 5000
  res <- frec2(stopval = mpfr(stopval, .precision), 
               n = mpfr(1, .precision), 
               x = mpfr(x, .precision)
  )
  print(glue::glue("{stopval}: {formatMpfr(res, drop0trailing = TRUE)}"))
  res
}

sol_df <- data.frame(stopval = seq(111, 119, by = 2)) %>%
  #    mpfr   
  mutate(val1 = new("mpfr", unlist(purrr::map(stopval, frec2_wrap, x = 1))),
         val2 = new("mpfr", unlist(purrr::map(stopval, frec2_wrap, x = 5))),
         delta = val1 - val2)

sol_txt_df <- sol_df %$%
  tibble(stopval = stopval,
         val1_txt = formatMpfr(val1, drop0trailing = TRUE),
         val2_txt = formatMpfr(val2, drop0trailing = TRUE),
         delta_txt = formatMpfr(delta, drop0trailing = TRUE))

P.S. . , . , , GNU MPFR.


« R ?».


All Articles