Как вычесть номера IEEE 754?

Как вычесть номера IEEE 754?

например: 0,546875 - 32.875...

-> 0,546875 является 0 01111110 10001100000000000000000 в IEEE-754

- > -32.875 является 1 10000111 01000101111000000000000 в IEEE-754

Итак, как мне сделать вычитание? Я знаю, что должен сделать оба показателя равными, но что мне делать после этого? 2'Complement мантиссы -32.875 и добавить с 0.546875 мантисса?

1 ответов


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

123400 - 5432 = 1.234*10^5 - 5.432*10^3

чем больше число доминирует, сдвиньте мантиссу меньшего числа в битное ведро, пока показатели не совпадут

1.234*10^5 - 0.05432*10^5

затем выполните вычитание с помощью мантисс

1.234 - 0.05432 = 1.17968
1.17968 * 10^5

затем нормализовать (что в данном случае и есть)

это было с базой 10 чисел.

в поплавке IEEE, одиночном точность

123400 = 0x1E208 = 0b11110001000001000
11110001000001000.000...

нормализовать, что мы должны сдвинуть десятичное число 16 мест влево так

1.1110001000001000 * 2^16

показатель смещен, поэтому мы добавляем 127 к 16 и получаем 143 = 0x8F. Это положительное число, поэтому бит знака равен 0 мы начинаем строить номер с плавающей запятой IEEE ведущий 1 Перед тем, как десятичное число подразумевается и не используется в одиночной точности, мы избавляемся от него и сохраняем дробь

знаковый бит, экспонента, мантисса!--21-->

0 10001111 1110001000001000...
0100011111110001000001000...
0100 0111 1111 0001 0000 0100 0...
0x47F10400

и если вы пишете программу, чтобы увидеть, что компьютер вещи 123400 вы получите то же самое:

0x47F10400 123400.000000

Итак, мы знаем экспоненту и мантиссу для первого операнда'

теперь второй операнд

5432 = 0x1538 = 0b0001010100111000

нормализовать, сдвинуть десятичные 12 бит влево

1010100111000.000
1.010100111000000 * 2^12

показатель смещен добавить 127 и получить 139 = 0x8B = 0b10001011

сложите все вместе

0 10001011 010100111000000
010001011010100111000000
0100 0101 1010 1001 1100 0000...
0x45A9C00

и a компьютерная программа / компилятор дает то же самое

0x45A9C000 5432.000000
чтобы ответить на ваш вопрос. Используя составные части чисел с плавающей запятой, я восстановил подразумеваемый 1 здесь, потому что нам это нужно
0 10001111 111100010000010000000000 -  0 10001011 101010011100000000000000

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

0 10001111 111100010000010000000000 -  0 10001011 101010011100000000000000
0 10001111 111100010000010000000000 -  0 10001100 010101001110000000000000
0 10001111 111100010000010000000000 -  0 10001101 001010100111000000000000
0 10001111 111100010000010000000000 -  0 10001110 000101010011100000000000
0 10001111 111100010000010000000000 -  0 10001111 000010101001110000000000

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

компьютеры выполняют вычитание, используя логику сложения, инвертируя второй оператор на пути в сумматор и утверждая бит переноса, например:

                         1
  111100010000010000000000
+ 111101010110001111111111
==========================

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

 1111000100000111111111111
  111100010000010000000000
+ 111101010110001111111111
==========================
  111001100110100000000000 

или сделайте это с помощью hex на вашем калькулятор

111100010000010000000000 = 1111 0001 0000 0100 0000 0000 = 0xF10400
111101010110001111111111 = 1111 0101 0110 0011 1111 1111 = 0xF563FF
0xF10400 + 0xF563FF + 1 = 0x1E66800
1111001100110100000000000 =1 1110 0110 0110 1000 0000 0000 = 0x1E66800

немного о том, как работает оборудование, так как это действительно вычитание с помощью сумматора, мы также инвертируем бит выполнения (или на некоторых компьютерах они оставляют его как есть). Так что выполнение 1-это хорошо, что мы в основном отбрасываем его. Если бы это был перенос нуля, нам потребовалось бы больше работы. У нас нет выполнения, поэтому наш ответ действительно 0xE66800.

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

111100010000010000000000 -  000010101001110000000000 = 
0xF10400 - 0x0A9C00 = 
0xE66800

теперь зачистка 1. откусив ответ, мы сложили части вместе

0 10001111 11001100110100000000000
01000111111001100110100000000000
0100 0111 1110 0110 0110 1000 0000 0000
0x47E66800

если вы следовали, написав программу для этого, я тоже это сделал. Эта программа нарушает стандарт C, неправильно используя объединение. Мне это сошло с рук с моим компилятором на моем компьютере, не ожидайте, что он будет работать все время.

#include <stdio.h>

union
{
    float f;
    unsigned int u;
} myun;


int main ( void )
{
    float a,b,c;

    a=123400;
    b=  5432;

    c=a-b;

    myun.f=a; printf("0x%08X %f\n",myun.u,myun.f);
    myun.f=b; printf("0x%08X %f\n",myun.u,myun.f);
    myun.f=c; printf("0x%08X %f\n",myun.u,myun.f);

    return(0);
}

и наш результат соответствует выходу вышеуказанной программы, мы получили 0x47E66800, делая это рука!--21-->

0x47F10400 123400.000000
0x45A9C000 5432.000000
0x47E66800 117968.000000

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

так:

1) извлеките части, знак, показатель, мантиссу.

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

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

4) Если результат равен нулю, то ваш ответ равен нулю, кодируйте значение IEEE для нуля в результате, иначе:

5) нормализовать число, сдвинуть ответ вправо или влево (ответ может быть 25 бит из 24 бит добавить/вычесть, добавить/вычесть может иметь драматический сдвиг для нормализации, либо один правый или много битов влево), пока у вас не будет 24-битного числа с наиболее значительным левым оправданным. 24 бита для одиночного поплавка точности. Более правильный способ определения нормализующее сместить влево или вправо, пока число напоминает 1.что-то. если у вас 0.001 вам будет сдвиг влево 3, Если у вас 11.10 вы бы сместить вправо 1. сдвиг влево увеличивает экспонента, сдвиг вправо уменьшает его. Не отличается от того, когда мы преобразовали из integer в float выше.

6) для одиночной точности извлеките руководство 1. из мантиссы, если показатель переполнен, вы попадаете в построение сигнального nan. Если биты знака были разными, и вы выполнили add, то вам нужно разобраться с выяснением бита знака результата. Если, как и прежде, все хорошо, вы просто поместите знак бит, показатель и мантиссу в результат

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