Iso*_*Bar 5 floating-point integer r ieee-754
我接到了用 R 为 AR.Drone 2.0 编写 API 的任务。我知道这可能不是最明智的语言选择,因为有用 Python 和 JS 编写的经过验证的良好 API,但我还是接受了挑战。
在我不得不格式化发送给无人机的 AT* 命令字符串之前,我做得很好。这些命令接受的参数可以是带引号的字符串、按原样发送的整数,也可以是必须表示为 32 位有符号整数的二进制和浮点数(-1 到 1 之间的单精度 IEEE754 浮点值)。
我能够通过 2 个在线转换器进行转换,首先从浮点数或二进制转换为十六进制,然后将十六进制转换为 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)
Run Code Online (Sandbox Code Playgroud)
此代码将产生以下输出:
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
Run Code Online (Sandbox Code Playgroud)
最后,我的问题是,如何在 R 中重现此功能/转换?
谢谢堆,伊多
编辑 1
我在 R 中找到了一个使用 base 函数进行二进制到 Int 转换的解决方案 strtoi
(land <- strtoi("10001010101000000000000000000", base=2))
[1] 290717696
(takeOff <- land + strtoi("1000000000", base=2))
[1] 290718208
Run Code Online (Sandbox Code Playgroud)
编辑 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"
Run Code Online (Sandbox Code Playgroud)
然后我使用了一个从 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"
Run Code Online (Sandbox Code Playgroud)
最后,我将它全部包装在一个函数中,通过将符号位粘贴在一起(始终使用“0”,但将整个字符串反转为负二进制并添加 - 符号到结果整数)、指数位(左填充 0)和尾数。我还添加了另一个函数,而不是strtoi无法处理负签名二进制文件(感谢我在 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"
Run Code Online (Sandbox Code Playgroud)
获得这个解决方案是一段相当长的旅程,我确信它不是最有效的代码实现(并且不确定它对于大于 1 或小于 -1 的浮点数是否正确),但它适用于我的目的。
任何关于如何改进此代码的评论都将受到高度重视。
干杯,伊多
| 归档时间: |
|
| 查看次数: |
1183 次 |
| 最近记录: |