[英]Mapping a ulong to a long in C#?
我正在嘗試將ulong映射為long(反之亦然),並將uint映射為int(反之亦然),如下所示-為了將值保存在具有簽名類型的MS-SQL數據庫中僅整數和biginteger。
我這樣做是因為我必須檢查(在數據庫中)數字(uint,ulong)是否在uint / ulong范圍(IPs-v4和v6)中的某個范圍內;實際上ulong實際上是一個uint128,由兩個烏龍)。
有沒有比我在這里的代碼更有效的方法來完成此操作:
public static ulong SignedLongToUnsignedLong(long signedLongValue)
{
ulong backConverted = 0;
// map ulong to long [ 9223372036854775808 = abs(long.MinValue) ]
if (signedLongValue < 0)
{
// Cannot take abs from MinValue
backConverted = (ulong)System.Math.Abs(signedLongValue - 1);
backConverted = 9223372036854775808 - backConverted - 1;
}
else
{
backConverted = (ulong)signedLongValue;
backConverted += 9223372036854775808;
}
return backConverted;
}
public static long UnsignedLongToSignedLong(ulong unsignedLongValue)
{
// map ulong to long [ 9223372036854775808 = abs(long.MinValue) ]
return (long) (unsignedLongValue - 9223372036854775808);
}
public static int UnsignedIntToSignedInt(uint unsignedIntValue)
{
// map uint to int [ 2147483648 = abs(long.MinValue) ]
return (int)(unsignedIntValue - 2147483648);
}
public static uint SignedIntToUnsignedInt(int signedIntValue)
{
uint backConverted = 0;
// map ulong to long [ 2147483648 = abs(long.MinValue) ]
if (signedIntValue < 0)
{
// Cannot take abs from MinValue
backConverted = (uint)System.Math.Abs(signedIntValue - 1);
backConverted = 2147483648 - backConverted - 1;
}
else
{
backConverted = (uint)signedIntValue;
backConverted += 2147483648;
}
return backConverted;
}
public static void TestLong()
{
long min_long = -9223372036854775808;
long max_long = 9223372036854775807;
ulong min_ulong = ulong.MinValue; // 0
ulong max_ulong = ulong.MaxValue; // 18446744073709551615 = (2^64)-1
long dbValueMin = UnsignedLongToSignedLong(min_ulong);
long dbValueMax = UnsignedLongToSignedLong(max_ulong);
ulong valueFromDbMin = SignedLongToUnsignedLong(dbValueMin);
ulong valueFromDbMax = SignedLongToUnsignedLong(dbValueMax);
System.Console.WriteLine(dbValueMin);
System.Console.WriteLine(dbValueMax);
System.Console.WriteLine(valueFromDbMin);
System.Console.WriteLine(valueFromDbMax);
}
public static void TestInt()
{
int min_int = -2147483648; // int.MinValue
int max_int = 2147483647; // int.MaxValue
uint min_uint= uint.MinValue; // 0
uint max_uint = uint.MaxValue; // 4294967295 = (2^32)-1
int dbValueMin = UnsignedIntToSignedInt(min_uint);
int dbValueMax = UnsignedIntToSignedInt(max_uint);
uint valueFromDbMin = SignedIntToUnsignedInt(dbValueMin);
uint valueFromDbMax = SignedIntToUnsignedInt(dbValueMax);
System.Console.WriteLine(dbValueMin);
System.Console.WriteLine(dbValueMax);
System.Console.WriteLine(valueFromDbMin);
System.Console.WriteLine(valueFromDbMax);
}
要從ulong
映射到long
,請long.MinValue
並添加long.MinValue
。 要從long
映射回ulong
,請減去long.MinValue
並進行long.MinValue
。 無論哪種情況,都應使用未經檢查的上下文,以便忽略溢出條件。
public static long MapUlongToLong(ulong ulongValue)
{
return unchecked((long)ulongValue + long.MinValue);
}
public static ulong MapLongToUlong(long longValue)
{
return unchecked((ulong)(longValue - long.MinValue));
}
uint
和int
的邏輯完全相似。
死靈法師。
基於Tanner Swett的答案的通用答案:
private static class Number<T>
{
private static object GetConstValue(System.Type t, string propertyName)
{
System.Reflection.FieldInfo pi = t.GetField(propertyName, System.Reflection.BindingFlags.Static
| System.Reflection.BindingFlags.Public
| System.Reflection.BindingFlags.NonPublic
);
return pi.GetValue(null);
}
private static T GetMinValue<T>()
{
return (T)GetConstValue(typeof(T), "MinValue");
}
private static T GetMaxValue<T>()
{
return (T)GetConstValue(typeof(T), "MaxValue");
}
private static System.Func<T, T, T> CompileAdd<T>()
{
// Declare the parameters
System.Linq.Expressions.ParameterExpression paramA =
System.Linq.Expressions.Expression.Parameter(typeof(T), "a");
System.Linq.Expressions.ParameterExpression paramB =
System.Linq.Expressions.Expression.Parameter(typeof(T), "b");
// Add the parameters
System.Linq.Expressions.BinaryExpression body =
System.Linq.Expressions.Expression.Add(paramA, paramB);
// Compile it
System.Func<T, T, T> add =
System.Linq.Expressions.Expression.Lambda<System.Func<T, T, T>>
(body, paramA, paramB).Compile();
return add;
}
private static System.Func<T, T, T> CompileSubtract<T>()
{
// Declare the parameters
System.Linq.Expressions.ParameterExpression paramA =
System.Linq.Expressions.Expression.Parameter(typeof(T), "a");
System.Linq.Expressions.ParameterExpression paramB =
System.Linq.Expressions.Expression.Parameter(typeof(T), "b");
// Subtract the parameters
System.Linq.Expressions.BinaryExpression body =
System.Linq.Expressions.Expression.Subtract(paramA, paramB);
// Compile it
System.Func<T, T, T> subtract =
System.Linq.Expressions.Expression.Lambda<System.Func<T, T, T>>
(body, paramA, paramB).Compile();
return subtract;
}
public static T MinValue = GetMinValue<T>();
public static T MaxValue = GetMaxValue<T>();
public static System.Func<T, T, T> Add = CompileAdd<T>();
public static System.Func<T, T, T> Subtract = CompileSubtract<T>();
}
public static TSigned MapUnsignedToSigned<TUnsigned, TSigned>(TUnsigned ulongValue)
{
TSigned signed = default(TSigned);
unchecked
{
signed = Number<TSigned>.Add((TSigned)(dynamic)ulongValue, Number<TSigned>.MinValue);
}
return signed;
}
public static TUnsigned MapSignedToUnsigned<TSigned, TUnsigned>(TSigned longValue)
{
TUnsigned unsigned = default(TUnsigned);
unchecked
{
unsigned = (TUnsigned)(dynamic) Number<TSigned>
.Subtract(longValue, Number<TSigned>.MinValue);
}
return unsigned;
}
當量:
// return MapUnsignedToSigned<ulong, long>(ulongValue);
private static long MapULongToLong(ulong ulongValue)
{
return unchecked((long)ulongValue + long.MinValue);
}
// return MapSignedToUnsigned<long, ulong>(longValue);
private static ulong MapLongToUlong(long longValue)
{
return unchecked((ulong)(longValue - long.MinValue));
}
盡管坦納·斯威特是正確的。 一個更好,更骯臟的解決方案是告訴.net將對ulong
訪問映射到與long
相同的內存地址。 這將為您提供瞬時轉換速度。
void Main()
{
var foo = new Foo { Long = -1 };
Console.WriteLine(foo.ULong);
}
// Define other methods and classes here
[StructLayout(LayoutKind.Explicit)]
public class Foo
{
[FieldOffset(0)]
private ulong _ulong;
[FieldOffset(0)]
private long _long;
public long Long
{
get { return _long; }
set { _long = value; }
}
public ulong ULong
{
get { return _ulong; }
set { _ulong = value; }
}
}
通過將實體框架POCO設置為使用顯示的屬性,可以控制字段映射到的內存地址。
因此,永遠不會發生轉換。
此代碼比Tanner Swett的代碼快100%。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.