Алгоритм сложения с плавающей точкой - PullRequest
2 голосов
/ 19 июня 2019

Я пытаюсь написать двоичный 8-битный алгоритм сложения с плавающей запятой для микроконтроллера picoblaze (1 знаковый бит, 4 экспонентных бита и 3 мантиссовых бита)

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

Моя основная проблема - установить знаковый бит результата, может кто-нибудь объяснить, как его правильно установить?

Моя идея состояла в том, чтобы проверить знак обоих чисел; затем, если они оба положительные, установите знак в 0, если они оба отрицательные, установите знак в 1 и используйте те же методы, что и раньше для сложения, и если один отрицательный, а другой положительный, сравните числа и используйте немного больше, но я не уверен, как сравнить два числа, и код становится немного загроможденным, есть ли лучший способ сделать это?

Ответы [ 3 ]

3 голосов
/ 19 июня 2019

Вам не нужно заботиться о знаке операндов, если вы превратите их в дополнение к двум.

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

  2. превратить числа в дополнение к двум. Для этого требуется дополнительный бит слева от мантиссы, чтобы учесть знаковый бит, и еще один бит, чтобы справиться с дополнительными переполнениями. В результате отрицательные числа будут представлены числом $ gt; 2, это дополнение их абсолютного значения к 2 ^ 3. Обратите внимание, что два старших значащих бита всегда равны.

  3. Выполнить сложение.

  4. обнаружение переполнения. Если два старших значащих бита результата не равны, происходит переполнение. В этом случае вы должны сделать арифметическое правое смещение результата и увеличить показатель степени.

  5. обнаружение недостаточного количества. Если три цифры слева от точки равны, это означает, что имеется недостаток. В этом случае выполните сдвиг влево до тех пор, пока эти три цифры не станут разными или все биты справа от точки не будут равны нулю, и отрегулируйте соответственно показатель степени.

  6. округление

  7. вернуться к дополнению до двух к знако-абсолютному значению и определить знак результата из его MSB.

* +1032 * Пример: * 1 033 *
A=1.1 B=-1.1 2^-1

1. alignment. Numbers are extended to 6 bits right of point.

A=+1.100000
B=-0.110000

2. two's complement
A=001.100000
B=2C(000.110000)=111.010000

3 addition

A       001.100000
+B      111.010000
=       000.110000

4 overflows none

5 underflows: shift result left 1 step and decrement exponent
001.100000 2^-1

6 rounding
001.100 2^-1

6 back to sign absolute value
+ (1.)100 2^-1

Еще один пример с отрицательным результатом

A=1.01 B=-1.1

1. alignment. Numbers are extended to 6 bits right of point.

A=+1.010000
B=-1.100000

2. two's complement
A=001.010000
B=2C(001.100000)=110.100000

3 addition

 A      001.010000
+B      110.100000
=       111.110000

4 overflows none (none overflow can happen if signs are different)

5 underflows: shift result left 2 steps and decrement exponent by 2
111.000000 2^-2

6 rounding
111.000 2^-2 (<0)

6 back to sign absolute value
-(1.)000 2^-2
3 голосов
/ 19 июня 2019

В общем (игнорируя такие вещи, как NaN), для A = B + C:

  • , если C имеет большую величину, чем B, поменяйте местами B и C такчто вы знаете, что B должен иметь "большую или равную" величину. Примечание: величина игнорирует знаковые биты (например, -6 имеет большую величину, чем +4, потому что 6> 4).

  • , если B и C имеютразные знаки, отрицай C и делай subtract_internal;иначе сделайте add_internal.

  • для subtract_internal, игнорируйте знаковые биты, вычтите величины (не забывая, что B должна иметь "большую или равную" величину), затем установитезнак A равен знаку B или C (они все равно будут иметь одинаковый знак).

  • для add_internal, игнорировать биты знакадобавьте величины, затем установите знак A равным знаку B или C (они все равно будут иметь одинаковый знак).

Также,в общем (игнорируя такие вещи, как NaN), для A = B - C:

  • , если C имеет большую величину, чем B, поменяйте местами B и C и отрицайте обаих (например, A - C == (-C) - (-A)), чтобы вы знали, что B должны иметь "большую или равную" величину.

  • , если B и C имеют разные знаки, отрицание C и до add_internal;еще сделать subtract_internal.

2 голосов
/ 19 июня 2019

Вам повезло.Предполагая, что вы используете представление, подобное IEEE754 (т. Е. Экспонента хранится с соответствующим смещением), вы можете просто сравнить строки битов лексикографически после небольшого массажа.Обратите внимание, что это предполагает, что вы уже обработали значения NaN соответствующим образом, поскольку значения NaN должны просто распространяться через ваш сумматор.

Хитрость заключается в следующем:

  • Вы игнорируете знак -0 (т. Е.если у вас есть 10000000, то обработайте это как 00000000.)
  • Если бит знака равен 1, то перевернуть все биты (включая бит знака)
  • Если бит знака равен 0, топереверните бит знака (оставьте те же самые биты)

Теперь вы можете сравнить эти две строки битов лексикографически, та, которая находится раньше в порядке словаря, меньше.Возможно, вам придется тщательно разобраться, как вы обрабатываете -0, но я подозреваю, что это не очень большая проблема для вас.

На самом деле, это именно та причина, по которой показатели хранятся с предвзятостью, так что вы можетесравнивайте числа с плавающей точкой, просто обрабатывая их как числа без знака, после выполнения трюка с переворотом, о котором я упоминал выше.

...