Я пытаюсь портировать функцию C ++, которая использует побитовые операции, на C #, но сталкиваюсь с проблемами. А именно, когда вход 0x01123456
C # возвращает ноль, но так должно быть 12
BN_set_word и другие функции BN_ * находятся в OpenSSL. Что делают эти функции (подробно) … Есть ли .NET-эквивалент в большом целом числе?
Что такое представление MPI? (Google бесполезен)
Должен ли я беспокоиться о маскировке в смене как уже упоминалось в комментариях здесь?
C ++ Original
// The "compact" format is a representation of a whole
// number N using an unsigned 32bit number similar to a
// floating point format.
// The most significant 8 bits are the unsigned exponent of base 256.
// This exponent can be thought of as "number of bytes of N".
// The lower 23 bits are the mantissa.
// Bit number 24 (0x800000) represents the sign of N.
// N = (-1^sign) * mantissa * 256^(exponent-3)
//
// Satoshi's original implementation used BN_bn2mpi() and BN_mpi2bn().
// MPI uses the most significant bit of the first byte as sign.
// Thus 0x1234560000 is compact (0x05123456)
// and 0xc0de000000 is compact (0x0600c0de)
// (0x05c0de00) would be -0x40de000000
//
// Bitcoin only uses this "compact" format for encoding difficulty
// targets, which are unsigned 256bit quantities. Thus, all the
// complexities of the sign bit and using base 256 are probably an
// implementation accident.
//
// This implementation directly uses shifts instead of going
// through an intermediate MPI representation.
CBigNum& SetCompact(unsigned int nCompact)
{
unsigned int nSize = nCompact >> 24;
bool fNegative =(nCompact & 0x00800000) != 0;
unsigned int nWord = nCompact & 0x007fffff;
if (nSize <= 3)
{
nWord >>= 8*(3-nSize);
BN_set_word(this, nWord);
}
else
{
BN_set_word(this, nWord);
BN_lshift(this, this, 8*(nSize-3));
}
BN_set_negative(this, fNegative);
return *this;
}
C # попытка порта
internal static System.Numerics.BigInteger SetCompact(uint numToCompact)
{
//
//
// SetCompact
// Extract the number from bits 0..23
uint nWord = numToCompact & 0x007fffff;
BigInteger ret = new BigInteger(nWord);
// Add zeroes to the left according to bits 25..32
var ttt = ret.ToByteArray();
uint size = numToCompact >> 24;
uint amountToShift = 0;
if (size <= 3)
{
amountToShift = 8 * (3 - size);
ret = ret >> (int)amountToShift;
}
else
{
ret = ret << (int)amountToShift;
amountToShift = 8 * (size - 3);
}
// Set the value negative if required per bit 24
UInt32 isNegative = 0x00800000 & numToCompact;
if (isNegative != 0)
ret =BigInteger.Negate(ret);
var test = ret.ToByteArray();
Console.WriteLine();
Console.WriteLine(ret.ToString("X"));
return ret;
}
Задача ещё не решена.
Других решений пока нет …