簡體   English   中英

在C#中將ulong映射為long?

[英]Mapping a ulong to a long in C#?

我正在嘗試將ulong映射為long(反之亦然),並將uint映射為int(反之亦然),如下所示-為了將值保存在具有簽名類型的MS-SQL數據庫中僅整數和biginteger。

我這樣做是因為我必須檢查(在數據庫中)數字(uint,ulong)是否在uint / ulong范圍(IPs-v4和v6)中的某個范圍內;實際上ulong實際上是一個uint128,由兩個烏龍)。

長龍

UIntToInt

有沒有比我在這里的代碼更有效的方法來完成此操作:

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));
}

uintint的邏輯完全相似。

死靈法師。
基於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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM