【问题标题】:How to normalize the sum of two IEEE754 single precision numbers?如何标准化两个 IEEE754 单精度数之和?
【发布时间】:2019-05-15 07:52:08
【问题描述】:

我正在 SystemVerilog 中设计一个浮点单元,它接受两个 IEEE754 格式的 32 位输入,将它们相加,然后以相同的 32 位 IEEE754 格式输出结果。

我的问题是,我如何判断我的结果是否需要标准化?

我意识到这是当您需要将“最左边”的 1 移动到正确的位时,应该是位 23。(从位 0 开始)

我很难理解如何确定正确的“最左边”1 位是什么,以便我可以移动尾数​​并适当地增加/减少指数位。

如果我的理解是正确的,加法应该有以下过程。

  • 将位分为符号、指数和尾数
  • 在尾数前添加“1”
  • 比较指数并将差值添加到较小的指数
  • 将较小指数的尾数向右移动所述差异以正确“排列”小数/数字
  • 执行二进制加法
  • 必要时标准化结果

我相信除了规范化部分之外,我的每一步都是正确的。我的问题是,如果我只有比特,我怎么能确定结果没有标准化?

我知道如果结果不是 1.(分数),它就没有被规范化。
IE。 10.10101 * 2^1 应归一化为 1.010101 *2^2, .1001 * 2^2 应归一化为 1.001 * 2^1。

具体来说,我想我想问我如何在添加两个数字后跟踪“小数”位的位置。

例如:添加输入 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

这里我们看到“最左边”的 1 是第 24 位而不是第 23 位,因此我们将尾数向右移动 1 并增加指数以标准化结果。然后我们删除“最左边”的 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)

如果我遵循前一种情况,这意味着不包括符号位的“最左边的 1”位将是 24 位,这意味着我会将尾数向右移动并增加指数。然而正确的答案是相反的! “'true' 最左边的 1”位实际上是位 22!这意味着我应该向左移动并减少!给我最终输出:

1 | 10001011 | 111 0101 1011 1111 0010 0000 (-7863.8906) 这是正确的。

类似地,将 0x45c59cbd 和 0xc473d9dc 相加得到尾数为

01 1010 0111 0010 0001 1000 0010 但“最左边的 1”位不是第 24 位,而是第 23 位,因此不需要归一化。

为什么在第一种情况下我需要担心第 24 位而不是其他两种情况?是因为我为其他情况添加了相反的符号吗?溢出问题?还是我从根本上缺少其他东西?

感谢您的帮助,如果格式不好,请见谅!

【问题讨论】:

    标签: floating-point verilog system-verilog ieee-754 twos-complement


    【解决方案1】:

    考虑在 IEEE-754 基本 32 位二进制格式中添加两个正数。当它们的有效位1 通过添加前导位完成,移位以对齐指数并添加时,前导位要么在相同的位置(因为没有发生进位),要么在左边一个(因为发生进位)。为了规范这一点,如果发生进位,只需右移一位即可。

    (如果两个数字都不正常,则前导位可能更靠右。但是,不会进行标准化,因为结果要么被带到使其正常的位置[因此不需要标准化],要么没有进到那个位置[所以结果仍然是次要的,不能归一化]。)

    如果两个数字都是负数,则同样的情况成立。有效数可以被视为绝对值,忽略符号位。

    如果数字有相反的迹象,就会出现并发症。该问题描述了在有效数字前加上一个符号位。这似乎不会导致正确的结果。例如,考虑添加 +1.125 和 -1.125。每个数字的四位有效数字是 1001。为符号位添加前缀分别为我们提供 01001 和 11001。然后将它们相加得到 1 00010(新的最左边的数字来自前一个最左边位置的进位)。不管我们如何对待前导位,低位都是错误的——0010 是不正确的;因为 +1.125 + −1.125 = 0,所以结果应该是 0000 并带有一些符号。因此,仅将符号位添加到有效数字的前缀不是正确的过程。

    我记得每个关于实现浮点加法的描述都指定在符号相反时使用减法而不是加法。在这种情况下,从较大(或相等)的数字中减去较小(或相等)的数字,然后必须左移一些(可能为零)位。

    在这个模型中,确定如何对数字进行归一化变得更加简单:

    • 添加符号相同的数字时,归一化需要根据是否从高位进行进位右移 0 或 1 位。 (请注意,可能会发生指数溢出。)
    • 当减去相反符号数时,标准化需要左移,直到前导一位处于正确位置或达到最小指数。

    我希望可以使用加法和二进制补码算法来实现混合符号的情况。在这种情况下,不应仅将符号位添加到有效数字的前面,而应通过反转每位然后加一来形成有效数字的二进制补码。一旦求和,如果它是负数,它可以再次补码,然后归一化。但是,您随后会在实现中添加更多附加项,以及它们的进位链依赖项。

    请注意,您还必须考虑对结果进行四舍五入,因为在移位期间可能会丢失一些位,以便在添加之前对齐指数,以及在移位期间以规范化添加相同符号数的结果。

    脚注

    1 “有效位”是浮点数小数部分的首选术语。 “尾数”是对数小数部分的历史术语。有效数字是线性的(将有效数字加倍会使表示的值加倍),而尾数是对数的(将尾数加倍使其所表示的值的部分平方)。

    【讨论】:

      猜你喜欢
      • 2013-01-03
      • 1970-01-01
      • 2021-10-06
      • 1970-01-01
      • 2020-04-06
      • 2018-10-12
      • 2015-05-08
      • 2014-08-11
      • 2019-10-10
      相关资源
      最近更新 更多