Формат single IBM float point преобразование в Csharp Single(float) формат - C#
Формулировка задачи:
Возникла проблема с чтением данных в формате IBM float point. Пытался найти какой-либо простой метод преобразования во внутренний форма CSharp, не вышло. Начал побайтно разбирать его, прочитал википедию. Там все просто:
SEF : S EEEEEEE FFFFFFFF FFFFFFFF FFFFFFFF
bits : 1 2 8 9 32
bytes : byte1 byte2 byte3 byte4
Первый бит - знак, потом экспонента(2-8 биты) и некий "Fractoin"- если, кто объяснит, как он на русском называется буду благодарен. Написал код:
1.Если у кого были подобные трудности, может поделитись опытом и объяснити странные повороты туда-сюда.
2. Может у кого-нибудь есть идеи оптимизации, слошком много циклов на мой взгляд.
public static float IBMEncoding(byte[] bInputBytes) { //Method of conversation from IBM Float point to Csharp single format. float fOutput = 0; //результат int A = 16; // Постоянный для IBM float множетиль int B = 64; // Константа степени. double dFraction = 0; // тот самый fraction= 1/2+1/4+...+(1/2)^n; int iExp = 0; // экспонентаю int iSign; //знак int[] b = new int[32]; #region Bit2Int // проблемы начались с самого начала данные в BigEndian формате Csharp упорно хотел LittleEndian // пришлось разворачивать. К тому же использование массива int мне показалось более удобным в // сравнении с использоавнием битных шифтов и прочих радостей вычлинения битов из байта. for (int j = 0; j < bInputBytes.Length; j++) { for (int i = 0; i < 8; i++) { b[31 - (j * 8 + i)] = bInputBytes[j] >> i & 0x1; ; ; }; }; #endregion iSign = Convert.ToInt32(Math.Pow(-1 , b[0])); // Получил знак собстевнно из первого бита. for (int i = 1; i < 8; i++) //Получаю значение экспоненты { iExp = Convert.ToInt32(iExp + Math.Pow(2, i-1) * b[8-i]); // Это место мне совершенно не понятно, может кто уточнит // Я использую обратный порядок для получения // экспоненты т.е. самые большие значения у меня слева. // Это единственный способ получения нужного результат // Если кто понимает в этом может объяснить как так? }; for (int i = 8; i < 32; i++) // Fraction { dFraction = dFraction + Math.Pow(0.5, i-8)*b[i]; //Получаю Fraction его уже не разворачиваю }; fOutput = Convert.ToSingle( iSign*dFraction*Math.Pow(A,(iExp-B))); // Все вставляю в окончательную формулу // и получаю искомое значение (проверено сторонним софтом) return fOutput; }
Решение задачи: «Формат single IBM float point преобразование в Csharp Single(float) формат»
textual
Листинг программы
float ibm = -157.1817f; var raw = *(int*)&ibm; var sign = raw >> 31 & 0x01; var exponent = raw >> 24 & 0x7f; var mantissa = (raw & 0x00ffffff) / (float)(1 << 24); var ieeeFloat = (1 - 2 * sign) * mantissa * (float)Math.Pow(16, exponent - 64);
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д