Перегрузка оператора и определение класса в R: используйте другое базовое поле/корпус

(Я использую слово "поле" в математическом смысле; базовые поля /corpora, которые R уже использует, включают действительные и комплексные числа.)

Я заинтересован в разрешении некоторых других базовых полей/корпусов (например, F₅, что является модульной арифметикой в ​​базе 5). Для этого мне нужно

  1. определить новый тип данных
  2. перегрузите соответствующие операторы (+, * и, возможно, больше)
  3. может быть, что-то еще? например, интегрировать с другими функциями?

Итак, как определить новый тип данных или операторы перегрузки в R?


person isomorphismes    schedule 05.11.2011    source источник
comment
Возможно, вы захотите начать с определения класса. Итак, выберите S3 или S4, затем определите класс. Перегрузка довольно проста там, где это разрешено (в большинстве мест). Какова конечная цель этого? Посмотрите, как ggplot перегружает оператор + для одного примера.   -  person Ari B. Friedman    schedule 06.11.2011
comment
@gsk3 gsk3 У вас есть ссылка на какую-то документацию? Я не знаю, как решить, что лучше для этой цели — S3 или S4. Цель состоит в том, чтобы иметь возможность выполнять матричные операции над различными полями и, таким образом, моделировать спорадические группы. Это можно сделать и на других языках, но я пытаюсь улучшить R.   -  person isomorphismes    schedule 06.11.2011


Ответы (2)


Я нашел вики по инструментам разработки Хэдли Уикхэма бесценным ресурсом для начала работы с классами в R. В частности, прочитайте разделы:

Вот отправная точка, иллюстрирующая некоторые концепции S3 классов. Назовем ваш новый класс f5. Как минимум, вы, вероятно, захотите создать методы для:

  • Принуждение: as.f5
  • Тест: is.f5
  • Некоторые основные операторы: +.f5
  • Класс для обработки печати: print.f5

Некоторый код (с использованием digitsBase в пакете GLDEX для базового преобразования):

library(GLDEX)

as.f5 <- function(x){
  if(!inherits(x, "f5")) class(x) <- c("f5", class(x))
  x
}

is.f5 <- function(x){
  inherits(x, "f5")
}

`+.f5` <- function(e1, e2){
  NextMethod(e1, e2)
}

print.f5 <- function(x, ...){
  # Next line from ?GLDEX::digitsBase
  b2ch <- function(db) noquote(gsub("^0+(.{1,})$"," \1", 
                           apply(db, 2, paste, collapse = "")))

  cat("Base 5:\n")
  cat(b2ch(digitsBase(x, 5)))
  invisible(x)
}


x <- as.f5(0:10)
y <- as.f5(5)

x + y

Base 5:
10 11 12 13 14 20 21 22 23 24 30
person Andrie    schedule 06.11.2011

Я интерпретировал ваш вопрос немного иначе, чем @Andrie, но он уже проделал кучу необходимой работы в классе S3. Я думал, вы хотите разработать групповые операции над группой из пяти элементов или, возможно, над кольцом. Затем вам понадобится операция «+» с элементом идентичности == 0 и, возможно, операция «*» с элементом идентичности == 1.

Если вы хотите, чтобы в это отображались неотрицательные целые числа, вы должны использовать арифметические операторы по модулю, %% и, возможно, %/%:

?Ops
as.g5 <- function(x){
  if(!inherits(x, "g5")) class(x) <- c("g5", class(x))
  x %% 5
}

print.g5 <- function(x, ...){

  cat("G5 equivalent:\n")
  cat(x %% 5)
  invisible(x)
}

Если вам нужны два оператора, вы можете искать:

 `+.g5` <- function(e1, e2){
   NextMethod(e1 ,e2) %% 5
 }

 `*.g5` <- function(e1, e2){
   NextMethod(e1 ,e2) %% 5
 }
 x <- as.g5(0:10)
 y <- as.g5(5)

 x + y
#G5 equivalent:
#0 1 2 3 4 0 1 2 3 4 0
 y <- as.g5(2)
 x * y
#G5 equivalent:
#0 2 4 1 3 0 2 4 1 3 0

Также возможно использовать эти операции с «изменчивыми» версиями векторов:

 as.g5(1:10) * as.g5(1:10)
# G5 equivalent:
# 1 4 4 1 0 1 4 4 1 0
person IRTFM    schedule 07.11.2011
comment
Спасибо. Вы правильно истолковали мой вопрос; это то, что я хочу сделать. Чем ваш ответ отличается от ответа @Andrie? - person isomorphismes; 08.11.2011
comment
Он продемонстрировал, как реализовать систему счисления с основанием 5, которая охватывает теоретически неограниченный (но практически ограниченный машинными и программными ограничениями) диапазон с помощью операции сложения. Я предложил конечную группу из 5 элементов с двумя операциями. (Если мне не изменяет память, я тоже построил кольцо.) - person IRTFM; 08.11.2011
comment
Да: поле — это коммутативное кольцо с мультипликативными инверсиями, поэтому все поля являются кольцами, но обратное неверно. Благодарю за разъяснение. Является ли ваш способ более эффективным с точки зрения памяти, поскольку он меньше? - person isomorphismes; 08.11.2011
comment
Я отмечаю, что каждый G5 с обычным умножением по модулю имеет обратный мультипликатив, поэтому я думаю, что выполнил все требования, за исключением, возможно, добавления операции g5/, но ваш путь к успеху кажется очевидным. - person IRTFM; 08.11.2011
comment
И я не думаю, что имеет смысл спрашивать об относительной эффективности двух методов, если они не дают одинаковых результатов. Конечная группа — это не тот же математический объект, что и реализация целых чисел методом печати с основанием 5. - person IRTFM; 15.01.2016