如何有效地序列化64位浮点数,以便字节数组保留自然数字顺序?

Thi*_*uda 3 javascript c python serialization natural-sort

我正在处理的项目要求我将javascript数字(这是双打)存储为数据库表中的BLOB主键(不能使用数据库本机浮点数据类型).所以基本上我需要将数字序列化为字节数组,方式如下:

1 - 字节数组的长度为8(这是序列化双精度通常所需的)

2 - 字节数组必须保持自然顺序,以便数据库透明地对索引b-tree中的行进行排序.

一个简单的函数,它接受一个数字并返回一个表示字节的数字数组,这正是我所寻求的.我更喜欢用javascript编写函数,但是java,C,C#,C++或python中的答案也会被接受.

Jan*_*ila 5

要满足分类要求,您需要:

  1. 使用big-endian表示
  2. 如果符号位为0,则将其翻转为1.检查实际位 - 将原始数字与0进行比较会在特殊情况下(如负零)给出不同的结果.
  3. 如果符号位为1,则翻转所有位

Python 3代码:

import struct

def invert(x):
    return bytes(c ^ 255 for c in x)

def tobin(x):
    binx = struct.pack('>d', x)
    if binx > b'\x80': #negative
        return invert(binx)
    else:
        return struct.pack('>d', -x)

data = [float('-inf'), -100.0, -2.0, -.9, -.1, -0.0, 
    0.0, .1, .9, 2.0, 100.0, float('inf'), float('nan')]

print(sorted(data, key=tobin))
#[-inf, -100.0, -2.0, -0.9, -0.1, -0.0, 0.0, 0.1, 0.9, 2.0, 100.0, inf, nan]
Run Code Online (Sandbox Code Playgroud)

在Python 2上更改invert为:

def invert(x):
    return "".join(chr(ord(c) ^ 255) for c in x)
Run Code Online (Sandbox Code Playgroud)

作为参考,这里是等效的node.js,它已经通过'Buffer'类实现了Big Endian序列化函数:

function serialize(n) {
  var buffer = new Buffer(8);
  var l = buffer.length;
  buffer.writeDoubleBE(n, 0);
  if (buffer[0] < 0x80) {
    buffer[0] ^= 0x80;
  } else {
    for (var i = 0; i < l; i++) 
      buffer[i] ^= 0xff;
  }
  return buffer
}

function deserialize(buffer) {
  var l = buffer.length;
  // 0x80 is the most significant byte of the representation of
  // the first positive number(Number.MIN_VALUE)
  if (buffer[0] >= 0x80) { 
    buffer[0] ^= 0x80;
  } else {
    for (var i = 0; i < l; i++) 
      buffer[i] ^= 0xff;
  }
  return buffer.readDoubleBE(0);
}
Run Code Online (Sandbox Code Playgroud)