0

Есть улов!Преобразование поплавка в целое число

У меня есть IEEE 754 одноточечная (32-разрядная) поплавка, хранящаяся в двух последовательных 16-битных целых числах.

Процессор, который я использую, не имеет математики с плавающей запятой или типов данных с плавающей запятой! То, что я хочу сделать, это преобразовать значение float в 16-разрядное целое число со знаком. Процессор имеет стандартные целочисленные математические и битовые манипуляции (маскировка, перемещение и т. Д.).

Я за исключением того, что мне нужно будет потерять некоторую точность при переходе от 32-битного поплавка к 16-битовому целому. Целочисленному числу также потребуется некоторый подразумеваемый коэффициент масштабирования, основанный на соответствующих диапазонах значений.

Вот простой пример, чтобы сделать вещи более ясными. Скажем, float имеет диапазон от 0.00 до 10.00. В этом случае я хочу, чтобы целое число находилось в диапазоне от 0 to 1000. Обратите внимание на подразумеваемой масштабный коэффициент 100. В этом случае целое число имеет подразумеваемое масштабирование 100.

Я знаю, что IEEE 754 содержит 1 бит знака, 8 бит для экспоненты (с 127 смещения) и 23 бит для мантиссы.

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

поплавкового значение = (-1)^Sign_bit * (1 + мантисса) * 2^(экспонент-127).

Основная проблема, которую я вижу, заключается в работе с 16-разрядными целыми знаками (диапазон от -32768 до +32767) и предотвращением переполнения или недостаточного потока.

+1

Я не понимаю, на что вы хотите ответить. –

ответ

0

Вы хотите преобразовать 32-битные поплавки в 16-битные целые числа с масштабированием. Однако пример, который вы даете, использует десятичное масштабирование, а не двоичное. Я не уверен, что вы хотите продолжать работать в двоичном домене в системе без блока с плавающей точкой или если вы действительно хотите преобразовать в десятичное представление числа.

Здесь я предполагаю, что ваша задача в том, что у вас нет доступа к инструкциям с плавающей запятой. Вы не указали язык программирования, поэтому я решил закодировать некоторые вещи на C#. Язык прост в использовании, но, возможно, не самый подходящий для бит-игры. Вам может быть проще и эффективнее реализовать это в C или C++.

Поскольку я буду продолжать использовать двоичное представление, масштаб не может быть числом 10 или 100 (интегральная мощность 10), но вместо этого должен быть интегральной мощностью 2. Ниже приведен класс, Число с плавающей запятой IEEE 754 разное.

class Ieee754Binary32 { 

    public Ieee754Binary32(Single value) { 
    using (var memoryStream = new MemoryStream()) { 
     var binaryWriter = new BinaryWriter(memoryStream); 
     binaryWriter.Write(value); 
     memoryStream.Seek(0, SeekOrigin.Begin); 
     var binaryReader = new BinaryReader(memoryStream); 
     var bits = binaryReader.ReadInt32(); 
     Fraction = bits & 0x7FFFFF; 
     Exponent = ((bits >> 23) & 0xFF) - 127; 
     Sign = (bits & 80000000) == 1 ? -1 : 1; 
    } 
    } 

    public Int32 Fraction { get; private set; } 

    public Int32 Exponent { get; private set; } 

    public Int32 Sign { get; private set; } 

    public Int16 ToScaledInt16(Int32 scaling) { 
    if (Exponent == -127 && Fraction == 0) 
     return 0; 
    var mantissa = 0x8000 | (Fraction >> 8); 
    var unscaledInt32 = Exponent >= 0 ? mantissa << Exponent : mantissa >> -Exponent; 
    var scaledInt16 = unscaledInt32 >> (15 - scaling); 
    return (Int16) (Sign*scaledInt16); 
    } 

} 

Метод ToScaledInt16 является то, что вы хотите использовать. Если вы хотите выразить цифры, используя доли 8, вы должны указать значение 3 за scaling. Все числа будут умножены на 2^3 = 8, например. 0.125 = 1/8 преобразуется в 1, 0,25 = от 2/8 до 2 и т.д.

Код не обрабатывает более сложные вещи, такие как округление, NaN или переполнение, но, возможно, вы можете использовать его в качестве отправной точки?

Смежные вопросы