我被赋予了为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
(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