代码之家  ›  专栏  ›  技术社区  ›  Aero Engy

将BCD的大numpy数组转换为十进制

  •  0
  • Aero Engy  · 技术社区  · 6 年前

    我有二进制数据文件在多GB的范围内,我是内存映射与numpy。每个数据包的开头都包含一个BCD时间戳。如果每个十六进制数被编码成0DDD:HH:MM:SS.ssss的时间格式,我需要把这个时间戳转换成当前年份的总秒数。

    Data Excerpt

    例子: 第一时间戳 0x0261 1511 2604 6002 将是:261:15:11:26.046002或

    261*86400 + 15*3600 + 11*60 + 26.046002 =  22551986.046002
    

    目前我这样做是为了计算时间戳:

    import numpy as np
    rawData  = np.memmap('dataFile.bin',dtype='u1',mode='r') 
    #findFrameStart returns the index to the start of each data packet   [0,384,768,...]
    fidx = findFrameStart(rawData)
    
    # Do lots of bit shifting and multiplying and type casting....
    day1  = ((rawData[fidx  ]>>4)*10 + (rawData[fidx  ]&0x0F)).astype('f8')
    day2  = ((rawData[fidx+1]>>4)*10 + (rawData[fidx+1]&0x0F)).astype('f8')
    hour  = ((rawData[fidx+2]>>4)*10 + (rawData[fidx+2]&0x0F)).astype('f8')
    mins  = ((rawData[fidx+3]>>4)*10 + (rawData[fidx+3]&0x0F)).astype('f8')
    sec1  = ((rawData[fidx+4]>>4)*10 + (rawData[fidx+4]&0x0F)).astype('f8')
    sec2  = ((rawData[fidx+5]>>4)*10 + (rawData[fidx+5]&0x0F)).astype('f8')
    sec3  = ((rawData[fidx+6]>>4)*10 + (rawData[fidx+6]&0x0F)).astype('f8')
    sec4  = ((rawData[fidx+7]>>4)*10 + (rawData[fidx+7]&0x0F)).astype('f8')
    time  = (day1*100+day2)*86400 + hour*3600 + mins*60 + sec1 + sec2/100 + sec3/10000 + sec4/1000000
    

    注:我必须将每个中间变量(第1天、第2天等)转换为两倍才能得到 time

    因为有很多帧, fidx

    1 回复  |  直到 6 年前
        1
  •  0
  •   Aero Engy    6 年前

    我对代码做了以下调整。这将修改 time 阵列就位&消除了对所有中间数组的需要。我没有给结果计时,但它需要的内存应该更少。

    time = np.zeros(fidx.shape,dtype='f8')
    scale = np.array([8640000, 86400, 3600, 60, 1, .01, .0001, .000001],dtype='f8')
    for ii,sf in enumerate(scale):
        time = time + ((rawData[fidx+ii]>>4)*10 + (rawData[fidx+ii]&0x0F))*sf