Wednesday, October 6, 2010

Convert decimal to IEEE-754 in R

For some theory on the standard IEEE-754, you can read the Wikipedia page. Here I will post only the code of the function to make the conversion in R.

First we write some functions to convert decimal numbers to binary numbers:

`decInt_to_8bit <- function(x, precs) {q <- c()r <- c()xx <- c()for(i in 1:precs){xx[1] <- xq[i] <- xx[i] %/% 2r[i] <- xx[i] %% 2xx[i+1] <- q[i]}rr <- rev(r)return(rr)}devDec_to_8bit <- function(x, precs) {nas <- c()nbs <- c()xxs <- c()for(i in 1:precs){xxs[1] <- x*2nas[i] <- (xxs[i]) - floor(xxs[i])nbs[i] <- trunc(xxs[i], 1)xxs[i+1] <- nas[i]*2}return(nbs)}`

For example, in 8-bit:

`decInt_to_8bit(11, 8)[1] 0 0 0 0 1 0 1 1`

`devDec_to_8bit(0.625, 8)[1] 1 0 1 0 0 0 0 0`

`devDec_to_8bit(0.3, 8)[1] 0 1 0 0 1 1 0 0devDec_to_8bit(0.3, 16)[1] 0 1 0 0 1 1 0 0 1 1 0 0 1 1 0 0`

We can delete the extra-zeros from the vectors, using these functions:

`remove.zero.aft <- function(a) {n <- length(a)for(i in n:1){if (a[n]==0) a <- a[-n]else return(a)n <- n-1}}remove.zero.bef <- function(a) {n <- length(a)for(i in 1:n){if (a[1]==0) a <- a[-1]else return(a)}}`

So we have:

`remove.zero.bef(decInt_to_8bit(11, 8))[1] 1 0 1 1remove.zero.aft(devDec_to_8bit(0.625, 8))[1] 1 0 1`

Binding these functions, we have:

`dec.to.nbit <- function(x,n) {aa <- abs(trunc(x, 1))bb <- abs(x) - abs(trunc(x))q <- c()r <- c()xx <- c()for(i in 1:n){xx[1] <- aaq[i] <- xx[i] %/% 2r[i] <- xx[i] %% 2xx[i+1] <- q[i]}rr <- rev(r)nas <- c()nbs <- c()xxs <- c()for(i in 1:n){xxs[1] <- bb*2nas[i] <- (xxs[i]) - floor(xxs[i])nbs[i] <- trunc(xxs[i], 1)xxs[i+1] <- nas[i]*2}bef <- paste(remove.zero.bef(rr), collapse="")aft <- paste(remove.zero.aft(nbs), collapse="")bef.aft <- c(bef, aft)strings <- paste(bef.aft, collapse=".")return(strings)}`

Example:

`dec.to.nbit(11.625,8)[1] "1011.101"`

Now we can write the code for the decimal to IEEE-754 single float conversion in R:

`dec.to.ieee754 <- function(x) {aa <- abs(trunc(x, 1))bb <- abs(x) - abs(trunc(x))rr <- decInt_to_8bit(aa, 32)ppc <- 24 - length(remove.zero.bef(rr))nbs <- devDec_to_8bit(bb, ppc)bef <- remove.zero.bef(rr)aft <- remove.zero.aft(nbs)exp <- length(bef) - 1mantissa <- c(bef[-1], aft)exp.bin <- decInt_to_8bit(exp + 127, 16)exp.bin <- remove.zero.bef(exp.bin)first <- c()if (sign(x)==1) first=c(0)if (sign(x)==-1) first=c(1)ieee754 <- c(first, exp.bin, mantissa, rep(0, 23-length(mantissa)))ieee754 <- paste(ieee754, collapse="")return(ieee754)}`

The numbers 11.625 and 11.33 in IEEE-754 are:

`dec.to.ieee754(11.625)[1] "01000001001110100000000000000000"dec.to.ieee754(11.33)[1] "01000001001101010100011110101110"`

You can verify the output with this Online Binary-Decimal Converter

1 comment:

1. HOLA!!! Tengo problemas con la conversion de numeros menores a 2. Cuando corro su script, me da diferente de los conversores ONLINE. Por ejemplo:
dec.to.ieee754(0.5)
[1] "0111111010000000000000000000000"

Pero en los conversores online la conversion da diferente:
00111111000000000000000000000000
(usando por ejemplo http://www.zator.com/Cpp/E2_2_4a1.htm