在 R 中将浮点数或二进制表示为 32 位有符号整数

Representing a float or a binary as a 32 bit signed integer in R

提问人:IsoBar 提问时间:9/17/2015 最后编辑:CommunityIsoBar 更新时间:9/19/2015 访问量:1657

问:

我接到了一个任务,要为 AR 编写一个 API。R 中的无人机 2.0。我知道这可能不是最明智的语言选择,因为有用 Python 和 JS 编写的经过验证的良好 API,但我还是接受了挑战。

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

我能够通过 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)

此代码将生成以下输出:

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

我在 R 中找到了一个解决方案,用于使用基本函数将二进制转换为 Intstrtoi

(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"

最后,我将其全部包装在一个函数中,通过将符号位(始终使用“0”,但反转了负二进制文件的整个字符串,并在生成的整数中添加了一个 - 符号)、指数位(左填充 0)和尾数,将浮点分数转换为二进制,然后转换为 32 位有符号整数。我还添加了另一个函数,而不是无法处理负符号二进制文件(感谢我在 SO 上找到的解决方案)。strtoi

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 的浮点数是否正确),但它适用于我的目的。

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

干杯,伊多

R 浮点 整数 IEEE-754

评论

0赞 tonytonov 9/21/2015
欢迎来到 SO!您可以随时将链接保留为纯文本,然后有人会将其编辑为超链接。
0赞 Carl Witthoft 10/27/2020
我想知道是否仔细使用并将完成此任务。看,为了一些帮助,但不是解决方案,stackoverflow.com/questions/39461349/......writeBinreadBin

答: 暂无答案