2012-02-17 2 views
5

Как объединить число с плавающей точкой до ближайшего целого? Я ищу алгоритм с точки зрения двоичного кода, так как я должен реализовать код в сборке.Округление до ближайшего целого числа с плавающей запятой

+1

Какое оборудование вы ориентируетесь? Для этого большинство аппаратных средств будут иметь специальные операции. Какой формат данных вы используете? –

+0

Мое оборудование не имеет инструкций с плавающей запятой. Я реализовал с плавающей точкой в ​​программном обеспечении. Архитектура представляет собой настраиваемый чип, реализованный моей группой, детали которой не важны. Поэтому я реализую плавающую точку IEEE-754, и мне нужно преобразовать ее в ближайшее целое число. Предпочтительно, число останется в формате с плавающей запятой. – Veridian

ответ

5

ОБНОВЛЕНО методом для правильного округления даже.

Базовый алгоритм:

Хранить 23-экспонент + 1'th бит (после запятой). Затем обнулите (23-экспоненциальные) младшие значащие биты. Затем используйте сохраненный бит и новый LSB для округления. Если сохраненный бит бит равен 1, добавьте его в LSB не усеченной части и при необходимости нормализуйте. Если сохраненный бит равен 0, ничего не делайте.

**

Для получения результатов, соответствующих стандарту IEEE-754:

** Перед обнуления (23-показатель) наименее значимых битов или вместе (22- экспоненты) младших значащих бит. Вызвать результат этого ИЛИ округляющего бита. Сохраненный бит (23-экспонента + 1) (после десятичной точки) будет называться бит защиты. Затем обнулите младшие значащие разряды (23-экспонента)).

Если бит защиты равен нулю, ничего не делайте.

Если бит охранник 1, и липкий бит 0, добавьте к LSB, если младший бит равен 1.

Если бит охранник 1 и липкий бит 1, добавьте к LSB.


Вот некоторые примеры с использованием базового алгоритма:

х = 62,3

sign exponent    mantissa 
x = 0  5  (1).11110010011001100110011 

Шаг 1: Хранить экспоненту + 1'th бит (после запятой)

Показатель 1 = 6-й бит

savedbit = 0

Шаг 2: ноль из 23-экспоненты наименее значимых битов 23-показатель = 18, поэтому мы обнулить 18 LSBs

sign exponent    mantissa 
x = 0  5  (1).11110000000000000000000 

Шаг 3: Используйте следующий бит для округления Поскольку хранится бит 0, мы ничего не делаем, а число с плавающей запятой округлено до 62.


Другой пример:

х = 21,9

sign exponent    mantissa 
x = 0  4  (1).01011110011001100110011 

Шаг 1: Хранить экспоненту + 1'th бит (после запятой)

показатель + 1 = 5-е бит

savedbit = 1

Шаг 2: ноль из 23-экспоненты наименее значимых битов 23-показатель = 19, таким образом, мы обнулить 19 LSBs

sign exponent    mantissa 
x = 0  4  (1).01010000000000000000000 

Шаг 3: Используйте следующий бит для округления Поскольку хранится бит равен 1 , мы добавим один к LSB усеченной части и получить 22, что правильный номер:

мы начинаем с:

sign exponent    mantissa 
x = 0  4  (1).01010000000000000000000 

Добавьте один в этом месте:

+       1 

И мы получаем 22:

sign exponent    mantissa 
x = 0  4  (1).01100000000000000000000 
+0

Почти; вам также нужно правильно обрабатывать полные случаи. –

+0

@ StephenCanon, я считаю, что мой алгоритм работает и для точных половинных случаев. Например, 21,5 раундов до 22, используя мой алгоритм. – Veridian

+0

Что относительно 20.5? –

-2

Уменьшите экспоненту на 1, добавьте 1, увеличьте показатель экспоненты на 1, обрезайте. Или просто добавьте 0.5 и усечь. Какой бы ни плавает ваша лодка.

+0

Умм..Я не понимаю, как это будет работать. Пример: x = 62,3, который должен быть округлен до 62. Двоичный код - 01000010011110010011001100110011. Таким образом, показатель составляет 5. По вашему методу экспонента становится 6, добавив, что один делает mantissa 10.11110010011001100110011, тогда вы сказали усечение. Поэтому я получаю 2 * 2^6 = 128. – Veridian

+0

Вы забыли «уменьшить». –

+0

2^5 становится 2^4, добавляет один, мантисса становится 10.11110010011001100110011, увеличивая показатель, 2^5, затем перемирие, 2 * 2^5 = 64, все еще некорректно. – Veridian

0

Существует инструкция SSE для округляется до ближайшего: http://www.musicdsp.org/showone.php?id=246

inline int float2int(float x) { 
    int i; 
    __asm { 
     fld x 
     fistp i 
    } 
    return i; 
} 
+0

Как можно использовать его на AltiVec? NEON? VIS? –

+0

Я не могу использовать функции, я должен писать в сборке (для процессора, над которым я работаю). Язык ассемблера не risc, ни x86, это собственный язык моих групп. Мне просто нужно знать, как манипулировать битами. Спасибо – Veridian

+0

Достаточно справедливо. Я оставлю свой ответ, хотя для дальнейшего использования. – tskuzzy

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