如何减去IEEE 754数字?

Tia*_*sta 9 math floating-point ieee-754

如何减去IEEE 754数字?

例如:0,546875 - 32.875 ...

- > 0,546875在IEEE-754中为0 01111110 10001100000000000000000

- > -32.875在IEEE-754中为1 10000111 01000101111000000000000

那么如何进行减法呢?我知道我必须使两个指数相等但在那之后我该怎么办?2'实施-32.875尾数并添加0.546875尾数?

old*_*mer 22

真的没有什么不同,你用铅笔和纸做.好吧有点不同

123400 - 5432 = 1.234*10^5 - 5.432*10^3
Run Code Online (Sandbox Code Playgroud)

较大的数字占主导地位,将较小数字的尾数移到比特桶中,直到指数匹配为止

1.234*10^5 - 0.05432*10^5
Run Code Online (Sandbox Code Playgroud)

然后用尾数进行减法

1.234 - 0.05432 = 1.17968
1.17968 * 10^5
Run Code Online (Sandbox Code Playgroud)

然后规范化(在这种情况下它是)

这是基数为10的数字.

在IEEE float中,单精度

123400 = 0x1E208 = 0b11110001000001000
11110001000001000.000...
Run Code Online (Sandbox Code Playgroud)

规范化我们必须将小数位16位置向左移动

1.1110001000001000 * 2^16
Run Code Online (Sandbox Code Playgroud)

指数是有偏差的,所以我们加127到16并得到143 = 0x8F.这是一个正数,所以符号位为0,我们开始构建IEEE浮点数,隐含小数前的前导1并且不以单精度使用,我们摆脱它并保持分数

符号位,指数,尾数

0 10001111 1110001000001000...
0100011111110001000001000...
0100 0111 1111 0001 0000 0100 0...
0x47F10400
Run Code Online (Sandbox Code Playgroud)

如果你编写一个程序来查看计算机东西123400是什么,你会得到同样的东西:

0x47F10400 123400.000000
Run Code Online (Sandbox Code Playgroud)

所以我们知道第一个操作数的指数和尾数'

现在是第二个操作数

5432 = 0x1538 = 0b0001010100111000
Run Code Online (Sandbox Code Playgroud)

标准化,左移12位

1010100111000.000
1.010100111000000 * 2^12
Run Code Online (Sandbox Code Playgroud)

指数偏置加127,得139 = 0x8B = 0b10001011

把它们放在一起

0 10001011 010100111000000
010001011010100111000000
0100 0101 1010 1001 1100 0000...
0x45A9C00
Run Code Online (Sandbox Code Playgroud)

并且计算机程序/编译器也提供相同的功能

0x45A9C000 5432.000000
Run Code Online (Sandbox Code Playgroud)

现在回答你的问题.使用浮点数的组成部分,我已经在这里恢复了隐含1,因为我们需要它

0 10001111 111100010000010000000000 -  0 10001011 101010011100000000000000
Run Code Online (Sandbox Code Playgroud)

我们必须像小学一样排列小数位,然后我们才能减去所以在这种情况下你必须将小的指数数字向右移动,将尾数位抛到末尾,直到指数匹配为止

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
Run Code Online (Sandbox Code Playgroud)

现在我们可以减去尾数.如果符号位匹配,那么我们将实际减去它们是否匹配,然后我们添加.他们匹配这将是一个减法.

计算机通过使用加法逻辑执行减法,在进入加法器的路上反转第二个运算符并断言进位,如下所示:

                         1
  111100010000010000000000
+ 111101010110001111111111
==========================
Run Code Online (Sandbox Code Playgroud)

而现在就像纸和笔一样,可以执行添加

 1111000100000111111111111
  111100010000010000000000
+ 111101010110001111111111
==========================
  111001100110100000000000 
Run Code Online (Sandbox Code Playgroud)

或者用计算器上的十六进制表示

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
Run Code Online (Sandbox Code Playgroud)

关于硬件如何工作的一点点,因为这实际上是使用加法器的减法,我们也反转了执行位(或者在某些计算机上它们保留原样).因此,执行1是一件好事,我们基本上放弃它.如果它是一个零的实现我们将需要更多的工作.我们没有执行,所以我们的答案真的是0xE66800.

很快就可以看到另一种方式,而不是反转和添加一个让我们只使用一个计算器

111100010000010000000000 -  000010101001110000000000 = 
0xF10400 - 0x0A9C00 = 
0xE66800
Run Code Online (Sandbox Code Playgroud)

通过尝试可视化它我可能会变得更糟.尾数减法的结果是111001100110100000000000(0xE66800),在最高有效位中没有移动,我们最终得到一个24位数,在这种情况下,msbit为1.没有归一化.要进行归一化,您需要向左或向右移动尾数,直到24位在最左侧位置排列最高位1,调整每个位移的指数.

现在剥离答案我们将各部分放在一起

0 10001111 11001100110100000000000
01000111111001100110100000000000
0100 0111 1110 0110 0110 1000 0000 0000
0x47E66800
Run Code Online (Sandbox Code Playgroud)

如果您一直在编写程序来执行此操作,我也这样做了.该程序以不正确的方式使用联合违反了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);
}
Run Code Online (Sandbox Code Playgroud)

我们的结果与上述程序的输出相匹配,我们得到了一个0x47E66800

0x47F10400 123400.000000
0x45A9C000 5432.000000
0x47E66800 117968.000000
Run Code Online (Sandbox Code Playgroud)

如果你正在编写一个程序来合成浮点数学,你的程序可以执行减法,你不必进行反转并加上一个东西,比上面看到的那样复杂.如果你得到一个否定的结果,虽然你需要使用符号位,反转你的结果,然后规范化.

所以:

1)提取部分,符号,指数,尾数.

2)通过从具有最小指数的数字中牺牲尾数位来对齐小数位,将该尾数向右移位直到指数匹配

3)如果符号位相同则为减法运算,则执行减法,如果符号位不同,则执行尾数的添加.

4)如果结果为零,那么您的答案为零,将IEEE值编码为零作为结果,否则:

5)规范化数字,将答案向右或向左移动(答案可以是24位加/减的25位,加/减可以有一个戏剧性的转换到标准化,左边一个右边或多个位)直到你有一个24位数字,其中最重要的一个左对齐.24位用于单精度浮点数.定义规范化的更正确的方法是向左或向右移动,直到数字类似于1.something.如果你有0.001你会向左移3,如果你有11.10你会向右移动1.向左移动会增加你的指数,右移会减少它.与我们从整数转换为浮动以上时没有什么不同.

6)对于单精度从尾数中移除前导1.如果指数已经溢出,则进入构建信令nan.如果符号位不同并且您执行了添加,那么您必须处理结果符号位.如果如上所述一切正常,你只需在结果中放置符号位,指数和尾数

乘法和除法是不同的,你问了减法,所以这就是我所涵盖的.