El uso de R en cálculos de precisión

Periódicamente, hay problemas, incluso en la vida cotidiana, cuando la precisión de bits float64/ int64no es suficiente para obtener una respuesta con la precisión requerida. ¿Corriendo en busca de otro instrumento? También una opción.


O no puede hacer esto, pero muestre curiosidad y descubra que, para calcular con precisión arbitraria, se ha hecho durante mucho tiempo la biblioteca GNU MPFR para la que hay contenedores para casi todos los idiomas. La práctica muestra que pocas personas están familiarizadas con esta biblioteca, que probablemente sea causada por las peculiaridades de los programas de estudio en las universidades y la corriente principal del programador posterior.


La biblioteca es buena y merece que se le preste atención, al menos en el marco de la ampliación de sus horizontes. En R hay un contenedor Rmpfr . A continuación, daré un ejemplo simple sobre los problemas para los escolares (bueno, no toquen los datos de diseño bajo el NDA) y tocaré varios rastrillos clásicos, que son atacados casi de inmediato.


Es una continuación de publicaciones anteriores .


Por ejemplo, tome el problema No. 39 de la competencia del año escolar 2019/2020 en el Quantum:
los números positivos x e y son tales que en la desigualdad debajo de la fracción izquierda es mayor que la derecha. ¿Cuál es mayor: x o y?


fracciones de cadena


Naturalmente, debe resolverse analíticamente (desigualdad alterna), pero esta no es una razón para no usarlo como demostración.


Dibujamos un código simple para calcular la secuencia de fracciones. Puede establecer inmediatamente el valor final, pero luego la escena de demostración para mpfr, así que avanzamos en pequeños pasos.


Resolvemos por métodos estándar
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)

Y aquí hay una mala suerte, ya en la decimocuarta iteración (número de parada = 29), la precisión no es suficiente para distinguir entre fracciones. ¡Y debes considerarlo hasta 2019!


Fracaso 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 . .


Fracaso 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