11

高値の符号なし整数 (最上位ビットを使用する値) を符号付き整数に変換できるようにしたいと考えています。この場合、値が符号付き整数型の最大値より大きくても構いません。ビット値が符号付き整数として表すものに変換したいだけです。つまり、負の数になることが予想されます。

ただし、VB.NET では、CType操作はそのようには機能しません (または や などの他の変換関数はいずれもCShort) CInteger。目的の符号付き型の最大値よりも大きい符号なし値を変換しようとするとOverflowException、負の数を返すのではなく、がスローされます。例えば:

Dim x As UShort = UShort.MaxValue
Dim y As Short = CShort(x)  ' Throws OverflowException

DirectCastどちらの型も他方を継承または実装しないため、符号付き型と符号なし型の間で値をキャストするために操作を使用できないことにも言及する価値があります。例えば:

Dim x As UShort = UShort.MaxValue
Dim y As Short = DirectCast(x, Short)  ' Won't compile: "Value of type 'UShort' cannot be converted to 'Short'

私は自分がやりたいことをする1つの方法を見つけましたが、それは不必要に醜いようです. これが私がそれを機能させる方法です:

Dim x As UShort = UShort.MaxValue
Dim y As Short = BitConverter.ToInt16(BitConverter.GetBytes(x), 0)  ' y gets set to -1

私が言ったように、それは機能しますが、VB.NET でそれを行うためのより簡単でクリーンな方法があれば、それが何であるかを知りたいです。

4

11 に答える 11

14

特にパフォーマンスのために、それを頻繁に使用している場合、を継続的に使用BitConverterすることは少し不便になります。それが私なら、直接変換を実行できるユーティリティライブラリをC#に追加して(とにかくunchecked通常uncheckedはC#のデフォルトですが)、そのライブラリを参照したくなるでしょう。別のオプションは、「共用体」構造体を悪用することかもしれません。以下は、VBにかなり簡単に変換できるはずです。

[StructLayout(LayoutKind.Explicit)]
struct EvilUnion
{
    [FieldOffset(0)] public int Int32;
    [FieldOffset(0)] public uint UInt32;
}
...
var evil = new EvilUnion();
evil.Int32 = -123;
var converted = evil.UInt32;

すなわち

<System.Runtime.InteropServices.StructLayout(Runtime.InteropServices.LayoutKind.Explicit)>
Structure EvilUnion
    <System.Runtime.InteropServices.FieldOffset(0)>
    Public Int32 As Integer
    <System.Runtime.InteropServices.FieldOffset(0)>
    Public UInt32 As UInteger
End Structure
...
Dim evil As New EvilUnion
evil.Int32 = -123
Dim converted = evil.UInt32
于 2013-02-05T13:50:33.287 に答える
2

VB6 の時代には、常に次のようなルーチンを作成する必要がありました。

Private Function ToShort(ByVal us As UShort) As Short
   If (us And &H8000) = 0 Then
      Return CType(us, Short)
   Else
      Return CType(CType(us, Integer) - UShort.MaxValue - 1, Short)
   End If
End Function

少なくとも.NETでは、これから拡張メソッドを作成して、より良いものにすることができます

于 2013-02-05T14:16:32.777 に答える
2

非常に簡単です:

32 ビットの場合

    Dim uVal32 As UInt32 = 3000000000
    Dim Val32 As Int32 = Convert.ToInt32(uVal32.ToString("X8"), 16)

val32 は終了 = -1294967296

16ビット用

    Dim uVal16 As UInt16 = 60000
    Dim Val16 As Int16 = Convert.ToInt16(uVal16.ToString("X4"), 16)

val16 は終了 = -5536

于 2015-08-19T19:54:43.003 に答える
0

ネクロマンシング。
Marc Gravell's answer の補足として、頭の中でそれを行う方法を知りたい場合は、次のようにします。

一般的に次のように記述できます。

<unsigned_type> value = unchecked(<unsigned_type>.MaxValue + your_minus_value + 1);

型チェックのため、コードは次のようになります。

public uint int2uint(int a)
{
    int sign = Math.Sign(a);
    uint val = (uint) Math.Abs(a);

    uint unsignedValue;
    if(sign > 0) // +a
        unsignedValue = unchecked(UInt32.MaxValue + val + 1);
    else // -a, a=0
        unsignedValue = unchecked(UInt32.MaxValue - val + 1);

    return unsignedValue;
}

そして、頭の中でやりたい場合は、次のようにすることができます。

BigInt mentalResult= <unsigned_type>.MaxValue + your_value;
mentalResult = mentalResult % <unsigned_type>.MaxValue;
if (your_value < 0) // your_value is a minus value
    mentalResult++;

// mentalResult is now the value you search
于 2015-11-12T09:55:23.810 に答える
-1

VB はわかりませんが、.NET コードなので C# に似ていると思います。C# では、単純に型キャストを使用できます。

UInt16 ui = 65000;
Int16   i = (Int16)ui;

終わり。

于 2017-01-25T15:28:50.810 に答える