【问题标题】:Rounding to the nearest integer in floating point舍入到浮点中最接近的整数
【发布时间】:2012-02-17 01:21:04
【问题描述】:

如何将浮点数四舍五入到最接近的整数?我正在寻找二进制的算法,因为我必须在汇编中实现代码。

【问题讨论】:

  • 您的目标是什么硬件?大多数硬件都会为此提供专门的操作。您使用的是什么数据格式?
  • 我的硬件没有浮点指令。我在软件中实现了浮点。架构是我组实现的定制芯片,细节不重要。所以我正在实现 IEEE-754 浮点,我需要转换为最接近的整数。最好,数字将保持浮点格式。

标签: math binary integer floating-point rounding


【解决方案1】:

更新了正确舍入为偶数的方法。

基本算法:

存储 23-exponent+1'th 位(小数点后)。接下来,将(23 指数)最低有效位清零。然后使用存储的位和新的 LSB 进行舍入。如果存储的位位为 1,则将非截断部分的 LSB 加 1,并在必要时进行归一化。如果存储位为 0,则什么也不做。

**

对于符合 IEEE-754 标准的结果:

** 在将 (23-exponent) 最低有效位清零之前,或将 (22-exponent) 最低有效位放在一起。调用该结果或舍入位。 存储的 (23-exponent + 1) 位(小数点后)将被称为保护位。 然后将(23-指数)最低有效位清零。

如果保护位为零,则什么也不做。

如果保护位为1,粘性位为0,如果LSB为1,则LSB加一。

如果保护位为 1,粘性位为 1,则在 LSB 上加一。


以下是一些使用基本算法的示例:

x = 62.3

    sign exponent             mantissa
x =  0      5       (1).11110010011001100110011

第一步:存储指数+1位(小数点后)

指数+1 = 第 6 位

保存位 = 0

第 2 步:将 23 指数最低有效位清零 23-exponent = 18,所以我们将 18 个 LSB 归零

    sign exponent             mantissa
x =  0      5       (1).11110000000000000000000

第 3 步:使用下一位进行舍入 由于存储的位为0,我们什么都不做,浮点数已经四舍五入到62。


另一个例子:

x = 21.9

    sign exponent             mantissa
x =  0      4       (1).01011110011001100110011

第一步:存储指数+1位(小数点后)

指数+1 = 第 5 位

保存位 = 1

第 2 步:将 23 指数最低有效位清零 23-exponent = 19,所以我们将 19 个 LSB 归零

    sign exponent             mantissa
x =  0      4       (1).01010000000000000000000

第 3 步:使用下一位进行舍入 由于存储的位是 1,我们将截断部分的 LSB 加 1,得到 22,也就是正确的数字:

我们从:

    sign exponent             mantissa
x =  0      4       (1).01010000000000000000000

在此位置添加一个:

+                          1

我们得到 22:

    sign exponent             mantissa
x =  0      4       (1).01100000000000000000000

【讨论】:

  • 几乎;您还需要正确处理中途案件。
  • @StephenCanon,我相信我的算法也适用于完全中间的情况。例如,21.5 轮到 22 使用我的算法。
  • @StephenCanon,它适用于 20.5,20.5 轮到 21。指数是 4,所以我们保留了尾数的 4 个最高有效位,但下一位是 1,所以我们在 LSB 上加了一个的截断位。所以在第 4 个位置(左起)添加了 1
  • 20.5 应该舍入到 20。请记住,在 IEEE-754 默认舍入中,精确的中途情况会被打破到偶数结果,而不是远离零。
  • 您将查看所有小数位,而不是只查看第一个小数位;如果小数位小于.100...,则什么也不做(就像您的代码现在所做的那样)。如果它们大于.100...,则在有效位上加一(就像您的代码现在所做的那样)。如果它们等于.100...,则仅当有效数字的 LSB 为 1 时才将有效数字加一。
【解决方案2】:

有一条 SSE 指令进行四舍五入:http://www.musicdsp.org/showone.php?id=246

inline int float2int(float x) {
    int i;
    __asm {
        fld x
        fistp i
    }
    return i;
}

【讨论】:

  • 如何在 AltiVec 上使用它?氖?可见光?
  • 我不能使用函数,我必须用汇编编写(对于我工作的处理器)。汇编语言不是 risc,也不是 x86,它是我小组自己的语言。我只需要知道如何操作这些位。谢谢
  • 很公平。我会留下我的答案以供将来参考。
  • 是的,希望有人能帮助有人浏览,谢谢。
【解决方案3】:

指数减1,加1,指数加1,截断。或者只是添加 0.5 并截断。让你的船浮起来。

【讨论】:

  • 嗯..我不明白这将如何工作。示例:x = 62.3,应该四舍五入到62。二进制是01000010011110010011001100110011。所以指数是5。按照你的方法,指数变成6,加一使尾数10.11110010011001100110011,然后你说截断。所以我得到 2*2^6 = 128。
  • 2^5变成2^4,加一,尾数变成10.11110010011001100110011,增加指数,2^5,然后截断,2*2^5 = 64,还是不正确。
  • 好的,那就换个方式吧。
  • 我认为你需要举一个例子来证明自己。当我计算出来时,这一切都被计算为错误的答案。
  • 10.101 -> 101.01 -> 110.01 -> 11.001 -> 11.
猜你喜欢
  • 2022-09-27
  • 2013-06-13
  • 1970-01-01
  • 2018-07-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-04
  • 1970-01-01
相关资源
最近更新 更多