C# с плавающей точкой в ​​двоичную строку и наоборот - PullRequest
1 голос
/ 12 января 2020

Я преобразовываю значение с плавающей запятой в двоичное представление строки:

float resulta = 31.0 / 15.0;    //2.0666666
var rawbitsa = ToBinaryString(resulta); //returns 01000000000001000100010001000100

, где ToBinaryString кодируется как:

static string ToBinaryString(float value)
{

        int bitCount = sizeof(float) * 8; // never rely on your knowledge of the size
        // better not use string, to avoid ineffective string concatenation repeated in a loop
        char[] result = new char[bitCount]; 

        // now, most important thing: (int)value would be "semantic" cast of the same
        // mathematical value (with possible rounding), something we don't want; so:
        int intValue = System.BitConverter.ToInt32(BitConverter.GetBytes(value), 0);

        for (int bit = 0; bit < bitCount; ++bit)
        {
            int maskedValue = intValue & (1 << bit); // this is how shift and mask is done.
            if (maskedValue > 0)
                maskedValue = 1;
            // at this point, masked value is either int 0 or 1
            result[bitCount - bit - 1] = maskedValue.ToString()[0];
        }

        return new string(result); // string from character array
}

Теперь я хочу преобразовать эту двоичную строку в значение с плавающей запятой .

Я попробовал следующее, но он возвращает значение "2.8293250329111622E-315"

string bstra = "01000000000001000100010001000100";
long w = 0;
for (int i = bstra.Length - 1; i >= 0; i--) w = (w << 1) + (bstra[i] - '0');
double da = BitConverter.ToDouble(BitConverter.GetBytes(w), 0); //returns 2.8293250329111622E-315

Я хочу значение "2.0666666", передав значение "01000000000001000100010001000100"

Почему я получаю неправильное значение? Я что-то упустил?

Спасибо.

1 Ответ

4 голосов
/ 12 января 2020

Вы делаете это намного сложнее, чем нужно; ошибка кажется в основном в коде парсинга символов, но вам не нужно делать все это .

Вместо этого вы можете попробовать вот так:

static string ToBinaryString(float value)
{
    const int bitCount = sizeof(float) * 8;
    int intValue = System.BitConverter.ToInt32(BitConverter.GetBytes(value), 0);
    return Convert.ToString(intValue, 2).PadLeft(bitCount, '0');
}

static float FromBinaryString(string bstra)
{
    int intValue = Convert.ToInt32(bstra, 2);
    return BitConverter.ToSingle(BitConverter.GetBytes(intValue), 0);
}

Пример:

float resulta = 31.0F / 15.0F; //2.0666666
var rawbitsa = ToBinaryString(resulta);
Console.WriteLine(rawbitsa); //01000000000001000100010001000100
var back = FromBinaryString(rawbitsa);
Console.WriteLine(back); //2.0666666

Обратите внимание, что использование GetBytes довольно неэффективно; если вы в порядке с кодом unsafe, вы можете удалить все это.

Также обратите внимание, что этот код определяется CPU c - это зависит от порядка байтов.

...