What is the best way to represent System.Double as a sortable string?

In data formats where all base types are strings, numeric types must be converted to a standardized string format that can be compared alphabetically. For example, a value shortfor a value 27can be represented as 00027if there are no negatives.

What is the best way to present doubleas a string? In my case, I can ignore the negatives, but I would be curious how you imagine a double in any case.

UPDATE

Based on Jon Skeet's suggestion, I now use this, although I am not 100% sure that it will work correctly:

static readonly string UlongFormatString = new string('0', ulong.MaxValue.ToString().Length);

public static string ToSortableString(this double n)
{
    return BitConverter.ToUInt64(BitConverter.GetBytes(BitConverter.DoubleToInt64Bits(n)), 0).ToString(UlongFormatString);
}

public static double DoubleFromSortableString(this string n)
{
    return BitConverter.Int64BitsToDouble(BitConverter.ToInt64(BitConverter.GetBytes(ulong.Parse(n)), 0));
}

UPDATE 2

I confirmed that John suspected that negatives did not work using this method. Here is a sample code:

void Main()
{
    var a = double.MaxValue;
    var b = double.MaxValue/2;
    var c = 0d;
    var d = double.MinValue/2;
    var e = double.MinValue;
    Console.WriteLine(a.ToSortableString());
    Console.WriteLine(b.ToSortableString());
    Console.WriteLine(c.ToSortableString());
    Console.WriteLine(d.ToSortableString());
    Console.WriteLine(e.ToSortableString());
}

static class Test
{
    static readonly string UlongFormatString = new string('0', ulong.MaxValue.ToString().Length);
    public static string ToSortableString(this double n)
    {
        return BitConverter.ToUInt64(BitConverter.GetBytes(BitConverter.DoubleToInt64Bits(n)), 0).ToString(UlongFormatString);
    }
}

:

09218868437227405311
09214364837600034815
00000000000000000000
18437736874454810623
18442240474082181119

, , .

3

. , !

+3
3

, (double.MaxValue 1.7976931348623157E + 308).

- ?

, , , - , double .

: BitConverter.DoubleToInt64Bits. .

, , DoubleToInt64Bits, , , , , , ...


, - ( ), ( ). :

static ulong EncodeDouble(double d)
{
    long ieee = System.BitConverter.DoubleToInt64Bits(d);
    ulong widezero = 0;
    return ((ieee < 0)? widezero: ((~widezero) >> 1)) ^ (ulong)~ieee;
}

static double DecodeDouble(ulong lex)
{
    ulong widezero = 0;
    long ieee = (long)(((0 <= (long)lex)? widezero: ((~widezero) >> 1)) ^ ~lex);
    return System.BitConverter.Int64BitsToDouble(ieee);
}

: http://ideone.com/JPNPY

, :

static string EncodeDouble(double d)
{
    long ieee = System.BitConverter.DoubleToInt64Bits(d);
    ulong widezero = 0;
    ulong lex = ((ieee < 0)? widezero: ((~widezero) >> 1)) ^ (ulong)~ieee;
    return lex.ToString("X16");
}

static double DecodeDouble(string s)
{
    ulong lex = ulong.Parse(s, System.Globalization.NumberStyles.AllowHexSpecifier);
    ulong widezero = 0;
    long ieee = (long)(((0 <= (long)lex)? widezero: ((~widezero) >> 1)) ^ ~lex);
    return System.BitConverter.Int64BitsToDouble(ieee);
}

: http://ideone.com/pFciY

+5

, , .

, , .

E000M3    +3.0
E001M2.7  +27.0

, , . , , IEEE .

+1

... org.apache.solr.util NumberUtils. , ( ) ( ). . :

  • Of course, NumberUtils is written in Java (not C #). My guess is that code can be converted to C # ... However, I am not very good at C #. The source is easily accessible on the Internet.
  • Received lines cannot be printed (in general).
  • The comments in the code show that all exotic cases, including negative numbers and infinities, should work correctly.
  • I have not done any tests ... However, based on a quick check of the code, this should be very fast.

The code below shows what needs to be done to use this library.

String key = NumberUtils.double2sortableStr(35.2);
0
source

All Articles