1

Is there a way to convert a float to an unsigned char fbytes[8] such that:

If float value f1 < f2, then fbytes1[i] should NEVER be greater than fbytes2[i] for 0 <= i <= 7?

The intention behind this is to serialize and store a floating point number and still be able to do comparisons by comparing byte by byte. E.g. even if the float is stored as raw bytes, I can sort rows by simple byte comparison and still preserve order.

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
jeffreyveon
  • 13,400
  • 18
  • 79
  • 129
  • 1
    Why do you need that *specific* numeric relationship? – Robert Harvey Aug 09 '17 at 02:20
  • 1
    left fill with zeroes – bruceg Aug 09 '17 at 02:21
  • I have no idea what is bing asked here. How are you converting the float to an array of bytes? – user3344003 Aug 09 '17 at 02:21
  • @RobertHarvey To serialize and store a floating point number and still be able to do comparisons by comparing byte by byte. – jeffreyveon Aug 09 '17 at 02:21
  • 1
    A single-precision floating point is represented by a sign bit, eight bits for the exponent and 23 bits for the mantissa. It should be a relatively simple matter to arrange those bits so that the numeric ordering is preserved. It won't be the relationship you describe in your question, however. See https://en.wikipedia.org/wiki/Single-precision_floating-point_format – Robert Harvey Aug 09 '17 at 02:27
  • The [2nd part of this answer](https://stackoverflow.com/a/45190635/2410359) addresses OP's goal. – chux - Reinstate Monica Aug 09 '17 at 02:31
  • @jeffreyveon Does the linked answer meet your goal? Otherwise, please detail why this post is using 8 bytes to do something that should only take 4 - the typical size of a `float`. – chux - Reinstate Monica Aug 09 '17 at 02:36
  • 1
    I suspect the most robust solution would be to read the bytes back in to a floating-point variable and then compare the floating-point variables in the usual fashion. Anything "clever" that avoids that step will likely be slower and will also likely give the incorrect result in some cases. – Jeremy Friesner Aug 09 '17 at 02:37
  • 1
    @chux: it might take 8 bytes to assure the correct ordering. – Robert Harvey Aug 09 '17 at 02:38
  • a modern Intel processor does doubles as fast is ints. Why not just treat the data as doubles when it is on your side of the serialization? even if you have to C cast... – lakeweb Aug 09 '17 at 02:40
  • 1
    @lakeweb Many modern embedded process lack FP units and such integer based compares are _significantly_ faster. Of course OP's situation is not well known. – chux - Reinstate Monica Aug 09 '17 at 02:49
  • Hi @chux yes. I've written a trig lib in integer form for a small micro. The op will have to chime in about his target... – lakeweb Aug 09 '17 at 02:54

2 Answers2

4

If you ignore NANs (which always compare unequal to everything, including themselves), this is simple. Otherwise, it is impossible.

First, convert to a big-endian byte array directly.

The sign bit is the high bit of the first byte. The following bits are the exponent, and then the mantissa.

If the sign bit is not set, set it so that all positive numbers sort after all negative numbers.

Otherwise, apply the ~ operator to all bytes (or maybe do this while it's all packed in a single integer - why do you need bytes anyway?). This will reverse the sort order within the negative numbers, as well as moving them below the positive numbers.

You may also want to coalesce zeros (if the only bit set anywhere is the sign bit, clear it).

o11c
  • 15,265
  • 4
  • 50
  • 75
2

If your floating-point implementation uses IEEE-754 (most do), you can take advantage of a subtle design point: if you treat the bits of an IEEE floating-point value as a sign-magnitude representation of an integral value, the usual ordering comparisons on that value will give exactly the same order as the corresponding comparisons on the floating-point value, and provide a consistent ordering when NaNs are present (positive NaNs are greater than infinity and negative NaNs are less than -infinity). So check the sign bits: if they're different, the positive one is greater; if they're the same, compare the rest as if they were an integral value.

Pete Becker
  • 74,985
  • 8
  • 76
  • 165