我想将(64位)整数转换为词法可排序的字符串(即,我可以使用String.Compare对结果字符串进行排序,并获得与直接比较原始值相同的顺序)。 Jon Skeet为双打here提供了实施。我想对 Int64 (也是Int32,浮点数,日期时间,时间跨度,但我确信我可以从Int64到达那里)做同样的事情。
如何将C#中的System.Int64表示为词法可排序字符串?
我喜欢链接的实现使用ASCII字符(它是十六进制编码的),因此,如果不是严格的人类可读的话,它是模糊的人类可呈现的。
我正在寻找适用于Int64的所有有效正值和负值的方法。
这是一个适用于Jon Skeet实施“EncodeDouble”的测试,以及每种方法的实现。我的实现与链接的问题没有变化,但提供了完整性。
[TestMethod]
public void LexicallySortRandomDoubles()
{
var r = new Random(15245);
for (int i = 0; i < 10000; ++i)
{
var bytes = new byte[16];
r.NextBytes(bytes);
var a = BitConverter.ToDouble(bytes, 0);
var b = BitConverter.ToDouble(bytes, 8);
// don't sort equal values, or nans.
if (double.IsInfinity(a) || double.IsNaN(a) || double.IsInfinity(b) || double.IsNaN(b)) continue;
var c = LexicallySortableValues.EncodeDouble(a);
var d = LexicallySortableValues.EncodeDouble(b);
// Comparison works
Assert.IsTrue(
a < b == System.String.Compare(c, d, System.StringComparison.InvariantCultureIgnoreCase) < 0,
string.Format("i={4}, a = {0}, b = {1}, c = {2}, d = {3}", a, b, c, d, i));
}
}
public static ulong DoubleToSortableULong(double d)
{
long ieee = System.BitConverter.DoubleToInt64Bits(d);
const ulong widezero = 0;
return ((ieee < 0) ? widezero : ((~widezero) >> 1)) ^ (ulong)~ieee;
}
public static double SortableULongToDobule(ulong lex)
{
const ulong widezero = 0;
long ieee = (long)(((0 <= (long)lex) ? widezero : ((~widezero) >> 1)) ^ ~lex);
return System.BitConverter.Int64BitsToDouble(ieee);
}
public static string EncodeDouble(double d)
{
ulong lex = DoubleToSortableULong(d);
return lex.ToString("X16");
}
public static double DecodeDouble(string s)
{
ulong lex = ulong.Parse(s, System.Globalization.NumberStyles.AllowHexSpecifier);
return SortableULongToDobule(lex);
}
答案 0 :(得分:3)
为了处理Int64
的签名性质,我建议您通过添加-Int64.MinValue
将带符号的64位整数转换为无符号的64位值。选择移位保留顺序和移位值以确保结果始终在UInt64
变量中表示。
然后使用ToString("D20")
格式化为19位十进制数字。或者使用ToString("X16")
的16位十六进制数字。
实施这样的转变:
static UInt64 ShiftToUnsigned(Int64 sval)
{
unchecked
{
return (UInt64) (sval - Int64.MinValue);
}
}
然后转换为字符串可以是:
static string LexicallySortable(Int64 value)
{
return ShiftToUnsigned(value).ToString("X16");
}
然后这个程序
static void Main(string[] args)
{
Console.WriteLine(String.Compare(LexicallySortable(Int64.MinValue), LexicallySortable(-2)));
Console.WriteLine(String.Compare(LexicallySortable(-2), LexicallySortable(-1)));
Console.WriteLine(String.Compare(LexicallySortable(-1), LexicallySortable(0)));
Console.WriteLine(String.Compare(LexicallySortable(0), LexicallySortable(1)));
Console.WriteLine(String.Compare(LexicallySortable(1), LexicallySortable(Int64.MaxValue)));
Console.ReadLine();
}
根据需要输出一系列-1
值。