>>>>> "Andrej" == Andrej Kveder <[EMAIL PROTECTED]>
>>>>>     on Thu, 9 Oct 2003 10:09:22 +0200 writes:

    Andrej> Thanks for the suggestions..  The strsplit function
    Andrej> works great for the second question...  I will have
    Andrej> to come up with another solution to the first one,
    Andrej> since my problem would definetly involve a lot of
    Andrej> calculations and I think that current methods would
    Andrej> cause major computational congestion...  BUt here is
    Andrej> the outline of my problem... if anybody has an
    Andrej> idea...  In practice I start with 4 possible
    Andrej> correlations: -0.9, -0.1, 0.1, 0.9 and want to
    Andrej> construct all possible 3x3 correaltion matrices with
    Andrej> those values.  So I need to do all possible
    Andrej> permutations of a given length with replication. I
    Andrej> have a set of 4 distinct values and want to create
    Andrej> the permutations of length 3.  My idea was as
    Andrej> folows: specifing the sequence in base-4 form 0 to
    Andrej> 333 would account for all possible combinations.  I
    Andrej> checked some of the existing functions which were
    Andrej> either recursive and slow or without replication. I
    Andrej> think there was a thread on the list just a short
    Andrej> while ago.  If anybody has a hint to follow, i would
    Andrej> be more then glad to try it out...

So, what you really want is combinatorics and the are two
packages on CRAN that provide these.

Back to the original question: representing numbers in other
bases than 10 :

Several years ago, I had defined a "baseint" class (S3) and
methods for doing these base conversions -- for integers only.
I'm appending the R source file (baseint.R) with the
definitions.
As the header of the file says, I've always wanted to do this
in a much nicer way, but didn't get around to that.
actually, cbind.baseint() must have a bug.
In spite of all that it can be useful, e.g.

> (b1 <- baseint(0:10, 2))
 [1] 0{b}2    1{b}2    10{b}2   11{b}2   100{b}2  101{b}2  110{b}2  111{b}2 
 [9] 1000{b}2 1001{b}2 1010{b}2
> (o1 <- baseint(0:10, 8)) # octal : has special print form
 [1] 00  01  02  03  04  05  06  07  010 011 012
> (h1 <- baseint(0:17, 16))# hexadesimal
 [1] x0  x1  x2  x3  x4  x5  x6  x7  x8  x9  xa  xb  xc  xd  xe  xf  x10 x11
> c(b1) ## gives the char strings
 [1] "0"    "1"    "10"   "11"   "100"  "101"  "110"  "111"  "1000" "1001"
[11] "1010"
> c(baseint(1:64, 4))
 [1] "1"    "2"    "3"    "10"   "11"   "12"   "13"   "20"   "21"   "22"  
[11] "23"   "30"   "31"   "32"   "33"   "100"  "101"  "102"  "103"  "110" 
[21] "111"  "112"  "113"  "120"  "121"  "122"  "123"  "130"  "131"  "132" 
[31] "133"  "200"  "201"  "202"  "203"  "210"  "211"  "212"  "213"  "220" 
[41] "221"  "222"  "223"  "230"  "231"  "232"  "233"  "300"  "301"  "302" 
[51] "303"  "310"  "311"  "312"  "313"  "320"  "321"  "322"  "323"  "330" 
[61] "331"  "332"  "333"  "1000"
> 

###-------- BETTER Re-Write this completely:
### Change internal representation to "trivial":
###  keep integer, just add "base" and class
### 1) New  as.character.baseint()   [should do  what baseint() does now]
### 2) print.baseint() must use as.character.*
###
### Advantage:  Ops.*  Math.* will all trivially work!

### However: Make sure that there are still tools F1() or F2()  for
### =======   F1(  "10101" ,   2) |-> 21
###           F2(c(1,0,1,0,1), 2) |-> 21
### (about what  as.integer.baseint() does now

### Consider doing the above IN ADDITION to the class below, using
### NEW class "basedInt"

baseint <- function(n, base = 8)
{
    ## Purpose: turn integers into 'octals', 'hexadecimals', 'bits', ...
    ## -----------------------------------------------------------------------
    ## Arguments: n:    non-negative integer vector
    ##            base: integer >= 2
    ## -----------------------------------------------------------------------
    ## Author: Martin Maechler, Date: 25 Nov 1998, 14:59

    if(!is.numeric(n) ||
       any(n < 0, na.rm=TRUE) || any(n != trunc(n), na.rm=TRUE))
        stop("baseint only works for non-negative integers")
    att <- attributes(n)
    ll <- length(n)# no coercion to integer! Can have larger ones: 2^63
    if(any(n > .Machine$integer.max, na.rm=TRUE))
        warning("baseint:  possible precision loss for large 'n'")
    r <- character(ll)
    b <- as.integer(base[1])
    if(b <= 1) stop("base must be integer >= 2")
    maxdig <- 1 + floor(log(max(1,n, na.rm=TRUE), b))
    o.digits <- matrix(NA, ll, maxdig)
    mn0 <- m <- n
    m.non.0 <- rep(TRUE, ll)
    j <- 0
    while(j==0 || any(m != 0, na.rm=TRUE)) { ## && j < maxdig
        ## m.non.0: TRUE for indices k w/ m[k] > 0 ; mn0 == m[m.non.0]
        o.digits[ m.non.0, (j <- j+1)] <- rem <- mn0 %% b
        m[m.non.0] <- (mn0 - rem) %/% b
        m.non.0 <- m.non.0 & m != 0
        mn0 <- m[m.non.0]
    }
    if(j < maxdig) cat("\n\n*** baseint: didn't need all columns: j=",j,
                       " < maxdig =",maxdig,"\n\n")
    dig.code <-
    {
        if(b <= 10)
            function(d) paste(d, collapse="")
        else if(b <= 36)
            function(d) paste(c(paste(0:9),letters[1:(b-10)])[d+1], collapse="")
        else
            function(d) paste(d, collapse=",")
    }
    r <- apply(o.digits[,j:1, drop = FALSE], 1,
               function(v) dig.code(v[!is.na(v)]))
    if(any(ina <- is.na(n))) r[ina] <- NA
    attributes(r) <- att
    attr(r,"base") <- base
    class(r) <- c("baseint", class(r))
    r
}

as.integer.baseint  <- function(x)
{
  ## Purpose: Turn "baseint" object back to plain integer
  ## ----------------------------------------------------------------------
  ## Author: Martin M�chler, Date: 12 Aug 00, 09:33
  if(!is.baseint(x)) stop("argument is not \"baseint\" object")
  b <- attr(x,"base") ## stopifnot(b >= 2)
  code <- if(b > 36) "M" else if(b > 10) "A" else ""
  ch <- strsplit(x, if(code == "M")",")
  m.e1 <- max(if(code == "M")unlist(lapply(ch,length)) else nchar(x)) - 1
  trm <- b^(0:m.e1)
  if(code == "A") digs <- c(paste(0:9),letters[1:(b-10)])
  sapply(ch,
         if(code != "A")
         function(s) sum(as.integer(s) * trm[length(s):1])
         else # 10 < b <= 36 : 0..9 a..z
         function(s) sum((match(s,digs)-1) * trm[length(s):1]))
}

is.baseint <- function(i) inherits(i, "baseint")
as.baseint <- function(i) if(is.baseint(i)) i else baseint(i)

print.baseint <- function(bnum,..., base.sep = "{b}")
{
    if(!is.numeric(b <- attr(bnum,"base")))
        stop("invalid 'baseint' object")
    ch.b <-
        if(b == 8)      paste("0",bnum,sep="")
        else if(b == 16)paste("x",bnum,sep="")
        else paste(bnum,b, sep= base.sep)
    att <- attributes(bnum)
    attributes(ch.b) <- att[is.na(match(names(att), c("class","base")))]
    class(ch.b) <- class(bnum)[class(bnum) != "baseint"]
    print(ch.b, quote=FALSE, right=TRUE, ...)
    invisible(bnum)
}

"[.baseint" <- function (x, ...)
{
    attr <- attributes(x)
    r <- unclass(x)[...]
    attributes(r) <- c(attributes(r),
                       attr[is.na(match(names(attr), c("dim", "dimnames")))])
    r
}

cbind.baseint <- function(x, ...) {
    att <- attributes(x)
    ## now want : r <- cbind.default(x,...)   but cbind dispatches internally
    ##
    ## Both of these fail pretty funnily (and identically, looking at traceback)
    ##    r <- NextMethod("cbind", x, ...)
       r <- NextMethod("cbind")
    ## The following is ugly, only correct when x has one class (can be corr.)
    ## and gives an  INFINITE LOOP for 2 or more "baseint" arguments
    ##    (since cbind then dispatches on the 2nd arg which is not unclassed...)
    ## r <- cbind(unclass(x),...)

    attributes(r) <- c(attributes(r),
                       att[is.na(match(names(att), c("dim","dimnames")))])
    r
}

Martin Maechler <[EMAIL PROTECTED]>     http://stat.ethz.ch/~maechler/
Seminar fuer Statistik, ETH-Zentrum  LEO C16    Leonhardstr. 27
ETH (Federal Inst. Technology)  8092 Zurich     SWITZERLAND
phone: x-41-1-632-3408          fax: ...-1228                   <><
______________________________________________
[EMAIL PROTECTED] mailing list
https://www.stat.math.ethz.ch/mailman/listinfo/r-help

Reply via email to