在R

时间:2015-09-17 15:07:59

标签: r floating-point integer ieee-754

我被赋予了为R中的AR.Drone 2.0编写API的任务。我知道它可能不是最明智的语言选择,因为有很好的验证API用Python和JS编写,但我接受了挑战反正。

我做得非常好,直到我必须格式化为无人机发送的AT *命令字符串。 这些命令接受的参数可以是带引号的字符串,整数,按原样发送,或者二进制和浮点数(单精度IEEE754浮点值在-1到1之间),必须表示为32位有符号整数。

我能够通过2个在线转换器进行转换,首先从float或二进制转换为十六进制,然后转换为十六进制到32位有符号整数,因此我对最常见的值进行了基本转换;但是,我想使用R的内置函数或添加的包进行转换。 Python的struct函数可以轻松处理这个问题:

import struct
print "Float , Signed Integer"
for i in range(-10,10):
    z = float(i)/10
    Y = struct.unpack('i', struct.pack('f', z))[0]
    print "%.1f , %d" % (z,Y)

land = 0b10001010101000000000000000000
take_off = land + 0b1000000000
print "Binary representation is simple as just using the %d format:"
print "Land code: %d, Take off code: %d" % (land, take_off)

此代码将产生以下输出:

Float , Signed Integer
-1.0 , -1082130432
-0.8 , -1085485875
-0.6 , -1088841318
-0.4 , -1093874483
-0.2 , -1102263091
0 , 0
0.2 , 1045220557
0.4 , 1053609165
0.6 , 1058642330
0.8 , 1061997773
1 , 1065353216

Binary representation is simple as just using the %d format
Land code: 290717696, Take off code: 290718208

最后在我的问题中,如何在R中重现此功能/转换?

谢谢堆,Ido

修改1

我使用基函数strtoi

在R中找到了二进制到Int转换的解决方案
(land <- strtoi("10001010101000000000000000000", base=2))
[1] 290717696
(takeOff <- land + strtoi("1000000000", base=2))
[1] 290718208

修改2

保持扫描网络寻找解决方案,并找到一些结合在一起的方式,让我得到我想要的转换,可能不是最优雅的方式。 首先,我写了一个函数来计算尾数和指数:

find_mantissa <- function(f) {
  i <- 1 ; rem <- abs(f) ; mantissa <- NULL
  man_dec_point <- FALSE
  while (length(mantissa)<24) {
    temp_rem <- rem-2^-i
    if (!isTRUE(man_dec_point)) {
      if (temp_rem>=0) {
        man_dec_point <- TRUE 
        mantissa <- "." 
      }
    } else {
      mantissa<-c(mantissa,ifelse(temp_rem>=0, "1", "0"))
    }
    rem <- ifelse(temp_rem>=0, temp_rem, rem)
    i<-i+1 
    next
  }
  return(c(paste0(mantissa[-1], collapse=""),24-i))
}

find_mantissa(0.68)
[1] "01011100001010001111010" "-1"

然后我使用了一个我改编自r-bloggers的功能(道歉不包括链接,我只限于2个链接):

dec2binstr<-function(p_number) {
  bin_str<-NULL
  while (p_number > 0) {
    digit<-p_number %% 2
    p_number<-floor(p_number / 2)
    bin_str<-paste0(digit,bin_str)
  }
  return(bin_str)
}

dec2binstr(127-1)
[1] "1111110"

最后,我将它全部包装在一个函数中,将浮点数转换为二进制,然后通过将符号位粘贴在一起来转换为32位有符号整数(总是使用“0”,但为负二进制文件反转整个字符串并添加了 - 签名到结果整数),指数位(左边填充0)和尾数。我还添加了另一个函数,而不是strtoi无法处理负面签名二进制文件(感谢我找到here on SO的解决方案。)

str2num <- function(x) {
  y <- as.numeric(strsplit(x, "")[[1]])
  sum(y * 2^rev((seq_along(y)-1)))
}
float2Int <- function(decfloat){
  bit32 <- ifelse(decfloat<0,-1, 1)
  mantissa <- find_mantissa(decfloat)
  exp <- dec2binstr(127+as.numeric(mantissa[2]))
  long_exp <- paste0(rep("0",8-stri_length(exp)),exp)
  unsigned <- paste0(long_exp,mantissa[1] )
  if (decfloat<0) {
    unsigned <- sapply(lapply(strsplit(unsigned, split=NULL), 
                              function(x) ifelse(x=="0","1", "0")), paste0, collapse="")
  }
  binary <- paste0("0",unsigned)
  return(c(binary, bit32*str2num(binary)))
}

float2Int(0.468)
[1] "00111110111011111001110110110010" "1055890866"                      
> float2Int(-0.468)
[1] "01000001000100000110001001001101" "-1091592781"

这是一个很难实现这个解决方案的过程,我确信它不是最有效的代码实现(并且不确定它对于大于1或小于-1的浮点数是否正确),但它适用于我的目的。 / p>

任何评论如何改进此代码都将受到高度重视。

干杯,Ido

0 个答案:

没有答案