如何归一化两个 IEEE754 单精度数字的总和?
How to normalize the sum of two IEEE754 single precision numbers?
我正在 SystemVerilog 中设计一个浮点单元,它接受两个 IEEE754 格式的 32 位输入,将它们相加,并以相同的 32 位 IEEE754 格式输出结果。
我的问题是,如何判断我的结果是否需要标准化?
我意识到这是当你需要将 "leftmost" 1 移动到正确的位时,应该是位 23。(从位 0 开始)
我很难思考的是如何确定正确的 "leftmost" 1 位是什么,以便我可以适当地移动尾数和 increment/decrement 指数位。
如果我的理解正确的话,加法应该有以下过程。
- 将位分成符号、指数和尾数
- 在尾数前加一个“1”
- 比较指数并将差值添加到较小的指数
- 将较小指数的尾数向右移动所述差 'line' 正确 decimals/number
- 执行二进制加法
- 必要时标准化结果
我相信除了归一化部分外,我的每一步都正确。我的问题是,如果我只有位,我如何确定结果未标准化?
我知道如果结果不是1.(分数)是不归一化的。
IE。 10.10101 * 2^1 应该归一化为 1.010101 *2^2 和 .1001 * 2^2 应该归一化为 1.001 * 2^1.
具体来说,我想我想问的是如何在添加两个数字后跟踪 "decimal" 位置。
例如:添加输入 a: 0x3fc00000 (1.5) 和 b: 0x40500000 (3.25)
a = 0 | 0111 1111 | (1) 100 0000 0000 0000 0000 0000
b = 0 | 1000 0000 | (1)101 0000 0000 0000 0000 0000
a 的指数比 b 小 1,所以:
a = 0 | 1000 0000 | 0(1)10 0000 0000 0000 0000 0000
b = 0 | 1000 0000 | (1)101 0000 0000 0000 0000 0000
添加尾数将得到
的结果
1 0011 0000 0000 0000 0000 0000
这里我们看到 "leftmost" 1 是第 24 位而不是第 23 位,因此我们将尾数向右移动 1 并增加指数以标准化结果。然后我们删除 "leftmost" 1 因为它隐含在 IEEE754 格式中,我们得到:
0 | 1000 0001 | 001 1000 0000 0000 0000 0000 (4.75) 作为我们的最终输出是正确的。
给出这个例子,我认为我只需要检查以下情况:
- 如果尾数的第24位等于1,则尾数右移并递增指数
- 否则检查第 23 位是否为 1,如果为真则不需要归一化
- 否则校验第22位为1,则尾数左移,指数减
但是,我发现这仅适用于某些情况。我错过了什么?
在我的实现中,我创建了一个 26 位的值来保存两个尾数的和,我不确定这是否正确。第 25 位是尾数的符号,我认为我不需要,第 24 位和第 23 位是隐藏位,或者不会包含在最终输出中的位。
例如:0x449ebbc8 (1269.868163) + 0xc60eb709 (-9133.758561) 给我以下尾数:
11 0111 1010 1101 1111 1001 0000 注意这是 26 位 (25:0)
如果我遵循前面的情况,这意味着不包括符号位的 "leftmost 1" 位将是 24 位,这意味着我将尾数右移并递增指数。然而正确答案恰恰相反! “'true' 最左边的 1” 位实际上是位 22!这意味着我应该向左移动并递减!给我的最终输出:
1 | 10001011 | 111 0101 1011 1111 0010 0000 (-7863.8906) 这是正确的。
类似地,将 0x45c59cbd 和 0xc473d9dc 相加得到尾数
01 1010 0111 0010 0001 1000 0010 但 "leftmost 1" 位不是第 24 位,而是第 23 位,因此不需要标准化。
为什么对于第一种情况我需要担心第 24 位而不是其他两种情况?是因为我为其他情况添加了相反的符号吗?溢出问题?还是我从根本上缺少其他东西?
感谢您的帮助,如果格式不正确,我们深表歉意!
考虑添加两个 IEEE-754 基本 32 位二进制格式的正正规数。当它们的有效位 1 通过在前导位前加上前缀、移位以对齐指数并相加完成时,前导位要么在相同位置(因为没有进位发生),要么是一个到离开(因为发生进位)。要对此进行归一化,如果发生进位,只需右移一位。
(如果两个数字都低于正规化,则前导位可能更靠右。但是,不会进行归一化,因为结果要么被带入使其正常的位置[因此不需要归一化]或没有进到那个位置[所以结果仍然不正常,无法归一化]。)
如果两个数都是负数,则情况相同。有效数可以被视为绝对值,忽略符号位。
如果数字有相反的符号,则有并发症。该问题描述了在有效数字前加上一个符号位。这似乎不会导致正确的结果。例如,考虑添加 +1.125 和 −1.125。每个数字的四位有效数是 1001。给符号位加上前缀分别得到 01001 和 11001。然后将它们相加得到 1 00010(新的最左边的数字来自前一个最左边位置的进位)。无论我们如何对待前导位,低位都是错误的——0010 是不正确的;因为 +1.125 + −1.125 = 0,结果应该是 0000 和一些符号。因此,仅将符号位作为尾数的前缀是不正确的过程。
我记得每一个实现浮点加法的描述都指定在符号相反时使用减法而不是加法。在这种情况下,从较大(或相等)的数字中减去较小(或相等)的数字,然后必须向左移动一些(可能为零)位。
在这个模型中,确定如何归一化数字变得更简单:
- 添加同号数时,归一化需要右移零位或一位,具体取决于是否有从高位进位的进位。 (注意可能会出现指数溢出。)
- 当减去符号相反的数字时,归一化需要左移,直到前一位位于正确的位置或达到最小指数。
我希望可以使用加法和二进制补码算法来实现混合符号的情况。在这种情况下,不应仅仅将符号位作为尾数的前缀,而应通过反转每一位然后加一来形成尾数的二进制补码。一旦找到和,如果它是负数,它可以再次补码然后归一化。但是,您随后要向实现中添加更多附加项及其进位链依赖项。
请注意,您还必须考虑对结果进行四舍五入,因为在添加前对齐指数的移位过程中以及在对添加类似符号数字的结果进行归一化的移位过程中,可能会丢失一些位。
脚注
1 “有效数”是浮点数小数部分的首选术语。 “尾数”是对数的小数部分的历史术语。有效数是线性的(有效数加倍表示的值加倍)而尾数是对数的(尾数加倍是它表示的值的一部分的平方)。
我正在 SystemVerilog 中设计一个浮点单元,它接受两个 IEEE754 格式的 32 位输入,将它们相加,并以相同的 32 位 IEEE754 格式输出结果。
我的问题是,如何判断我的结果是否需要标准化?
我意识到这是当你需要将 "leftmost" 1 移动到正确的位时,应该是位 23。(从位 0 开始)
我很难思考的是如何确定正确的 "leftmost" 1 位是什么,以便我可以适当地移动尾数和 increment/decrement 指数位。
如果我的理解正确的话,加法应该有以下过程。
- 将位分成符号、指数和尾数
- 在尾数前加一个“1”
- 比较指数并将差值添加到较小的指数
- 将较小指数的尾数向右移动所述差 'line' 正确 decimals/number
- 执行二进制加法
- 必要时标准化结果
我相信除了归一化部分外,我的每一步都正确。我的问题是,如果我只有位,我如何确定结果未标准化?
我知道如果结果不是1.(分数)是不归一化的。
IE。 10.10101 * 2^1 应该归一化为 1.010101 *2^2 和 .1001 * 2^2 应该归一化为 1.001 * 2^1.
具体来说,我想我想问的是如何在添加两个数字后跟踪 "decimal" 位置。
例如:添加输入 a: 0x3fc00000 (1.5) 和 b: 0x40500000 (3.25)
a = 0 | 0111 1111 | (1) 100 0000 0000 0000 0000 0000
b = 0 | 1000 0000 | (1)101 0000 0000 0000 0000 0000
a 的指数比 b 小 1,所以:
a = 0 | 1000 0000 | 0(1)10 0000 0000 0000 0000 0000
b = 0 | 1000 0000 | (1)101 0000 0000 0000 0000 0000
添加尾数将得到
的结果1 0011 0000 0000 0000 0000 0000
这里我们看到 "leftmost" 1 是第 24 位而不是第 23 位,因此我们将尾数向右移动 1 并增加指数以标准化结果。然后我们删除 "leftmost" 1 因为它隐含在 IEEE754 格式中,我们得到:
0 | 1000 0001 | 001 1000 0000 0000 0000 0000 (4.75) 作为我们的最终输出是正确的。
给出这个例子,我认为我只需要检查以下情况:
- 如果尾数的第24位等于1,则尾数右移并递增指数
- 否则检查第 23 位是否为 1,如果为真则不需要归一化
- 否则校验第22位为1,则尾数左移,指数减
但是,我发现这仅适用于某些情况。我错过了什么?
在我的实现中,我创建了一个 26 位的值来保存两个尾数的和,我不确定这是否正确。第 25 位是尾数的符号,我认为我不需要,第 24 位和第 23 位是隐藏位,或者不会包含在最终输出中的位。
例如:0x449ebbc8 (1269.868163) + 0xc60eb709 (-9133.758561) 给我以下尾数:
11 0111 1010 1101 1111 1001 0000 注意这是 26 位 (25:0)
如果我遵循前面的情况,这意味着不包括符号位的 "leftmost 1" 位将是 24 位,这意味着我将尾数右移并递增指数。然而正确答案恰恰相反! “'true' 最左边的 1” 位实际上是位 22!这意味着我应该向左移动并递减!给我的最终输出:
1 | 10001011 | 111 0101 1011 1111 0010 0000 (-7863.8906) 这是正确的。
类似地,将 0x45c59cbd 和 0xc473d9dc 相加得到尾数
01 1010 0111 0010 0001 1000 0010 但 "leftmost 1" 位不是第 24 位,而是第 23 位,因此不需要标准化。
为什么对于第一种情况我需要担心第 24 位而不是其他两种情况?是因为我为其他情况添加了相反的符号吗?溢出问题?还是我从根本上缺少其他东西?
感谢您的帮助,如果格式不正确,我们深表歉意!
考虑添加两个 IEEE-754 基本 32 位二进制格式的正正规数。当它们的有效位 1 通过在前导位前加上前缀、移位以对齐指数并相加完成时,前导位要么在相同位置(因为没有进位发生),要么是一个到离开(因为发生进位)。要对此进行归一化,如果发生进位,只需右移一位。
(如果两个数字都低于正规化,则前导位可能更靠右。但是,不会进行归一化,因为结果要么被带入使其正常的位置[因此不需要归一化]或没有进到那个位置[所以结果仍然不正常,无法归一化]。)
如果两个数都是负数,则情况相同。有效数可以被视为绝对值,忽略符号位。
如果数字有相反的符号,则有并发症。该问题描述了在有效数字前加上一个符号位。这似乎不会导致正确的结果。例如,考虑添加 +1.125 和 −1.125。每个数字的四位有效数是 1001。给符号位加上前缀分别得到 01001 和 11001。然后将它们相加得到 1 00010(新的最左边的数字来自前一个最左边位置的进位)。无论我们如何对待前导位,低位都是错误的——0010 是不正确的;因为 +1.125 + −1.125 = 0,结果应该是 0000 和一些符号。因此,仅将符号位作为尾数的前缀是不正确的过程。
我记得每一个实现浮点加法的描述都指定在符号相反时使用减法而不是加法。在这种情况下,从较大(或相等)的数字中减去较小(或相等)的数字,然后必须向左移动一些(可能为零)位。
在这个模型中,确定如何归一化数字变得更简单:
- 添加同号数时,归一化需要右移零位或一位,具体取决于是否有从高位进位的进位。 (注意可能会出现指数溢出。)
- 当减去符号相反的数字时,归一化需要左移,直到前一位位于正确的位置或达到最小指数。
我希望可以使用加法和二进制补码算法来实现混合符号的情况。在这种情况下,不应仅仅将符号位作为尾数的前缀,而应通过反转每一位然后加一来形成尾数的二进制补码。一旦找到和,如果它是负数,它可以再次补码然后归一化。但是,您随后要向实现中添加更多附加项及其进位链依赖项。
请注意,您还必须考虑对结果进行四舍五入,因为在添加前对齐指数的移位过程中以及在对添加类似符号数字的结果进行归一化的移位过程中,可能会丢失一些位。
脚注
1 “有效数”是浮点数小数部分的首选术语。 “尾数”是对数的小数部分的历史术语。有效数是线性的(有效数加倍表示的值加倍)而尾数是对数的(尾数加倍是它表示的值的一部分的平方)。