To meet the sorting requirement, you need to:
- Use big-endian representation
- If the sign bit is 0, flip it to 1. Check the actual bit -- comparing the original number to 0 gives a different result in special cases such as the negative zero.
- If the sign bit is 1, flip all bits
Python 3 code:
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]
On Python 2 change invert
to:
def invert(x):
return "".join(chr(ord(c) ^ 255) for c in x)
For reference, here is the equivalent node.js which already implements a Big Endian serialization function through the 'Buffer' class:
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);
}