Nat*_*ley 3 .net c# sorting double
在所有基础类型都是字符串的数据格式中,必须将数字类型转换为标准化字符串格式,可以按字母顺序进行比较.例如,a short的值27可以表示为00027没有负数.
表示double字符串的最佳方法是什么?在我的情况下,我可以忽略否定,但我很好奇你在任何一种情况下如何代表双重.
UPDATE
基于Jon Skeet的建议,我现在正在使用它,虽然我不是100%确定它能正常工作:
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));
}
Run Code Online (Sandbox Code Playgroud)
更新2
我已经证实了Jon怀疑 - 使用这种方法的负面效果不起作用.以下是一些示例代码:
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);
}
}
Run Code Online (Sandbox Code Playgroud)
其中产生以下输出:
09218868437227405311
09214364837600034815
00000000000000000000
18437736874454810623
18442240474082181119
Run Code Online (Sandbox Code Playgroud)
显然没有按预期排序.
更新3
以下接受的答案是正确的答案.多谢你们!
考虑到巨大的范围(double.MaxValue1.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);
}
Run Code Online (Sandbox Code Playgroud)
演示在这里: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);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
804 次 |
| 最近记录: |