استخدام R في الحسابات الدقيقة

بشكل دوري ، هناك مشاكل ، حتى في الحياة اليومية ، عندما تكون دقة البت float64/ int64غير كافية للحصول على إجابة بالدقة المطلوبة. التسرع في البحث عن صك آخر؟ أيضا خيار.


أو لا يمكنك القيام بذلك ، ولكن أظهر الفضول واكتشف أنه للحساب بدقة تعسفية ، تم إنشاء مكتبة GNU MPFR منذ فترة طويلة والتي توجد بها أغلفة لجميع اللغات تقريبًا. تبين الممارسة أن القليل من الناس على دراية بهذه المكتبة ، والتي ربما تكون ناجمة عن خصوصية برامج الدراسة في الجامعات وما بعدها من التيار السائد للمبرمج.


المكتبة جيدة وتستحق الاهتمام بها ، على الأقل في إطار توسيع آفاقها. على R هناك غلاف Rmpfr . فيما يلي سأعطي مثالًا بسيطًا على المشكلات التي تواجه أطفال المدارس (حسنًا ، لا تلمس بيانات التصميم بموجب قانون عدم الإفشاء) وسوف أتطرق إلى عدد من المكابس الكلاسيكية ، التي تتم مهاجمتها على الفور تقريبًا.


إنه استمرار للمنشورات السابقة .


على سبيل المثال ، خذ المشكلة رقم 39 من مسابقة العام الدراسي 2019/2020 في الكم:
الأعداد الموجبة x و y بحيث تكون في عدم المساواة أسفل الكسر الأيسر أكبر من اليمين. أيهما أكبر: س أم ص؟


كسور السلسلة


بطبيعة الحال ، يجب حلها بشكل تحليلي (عدم المساواة بالتناوب) ، ولكن هذا ليس سببًا لعدم استخدامها كدليل.


نرسم رمزًا بسيطًا لحساب تسلسل الكسور. يمكنك على الفور تعيين القيمة النهائية ، ولكن بعد ذلك demoscene mpfr، لذلك نتحرك بخطوات صغيرة.


نحل بالطرق القياسية
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)

وهنا سوء الحظ ، بالفعل في التكرار الرابع عشر (رقم التوقف = 29) ، الدقة ليست كافية بالنسبة لنا للتمييز بين الكسور. وعليك التفكير حتى عام 2019!


الفشل 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 . .


الفشل 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