【问题标题】:converting floating point to 32-bit fixed point in Java在 Java 中将浮点数转换为 32 位定点数
【发布时间】:2010-08-04 04:57:42
【问题描述】:

我必须在 Java 中将浮点数转换为 32 位定点数。

不明白什么是 32 位定点?

任何机构都可以帮助算法吗?

【问题讨论】:

  • Java 不能进行类型转换? :O

标签: java algorithm math compression


【解决方案1】:

定点数是一个实数的表示,它使用一定数量的类型的位作为整数部分,其余的类型的位用于小数部分。代表每个部分的位数是固定的(因此得名定点)。整数类型通常用于存储定点值。

定点数通常用于不支持浮点数的系统,或者需要比浮点数提供的速度更快的系统。定点计算可以使用 CPU 的整数指令来执行。

32 位定点数将以 32 位类型存储,例如 int

通常(在这种情况下为无符号)整数类型中的每个位将表示一个整数值 2^n,如下所示:

 1    0    1    1    0    0    1    0       = 2^7 + 2^5 + 2^4 + 2^1 = 178
2^7  2^6  2^5  2^4  2^3  2^2  2^1  2^0

但如果该类型用于存储定点值,则对位的解释略有不同:

 1    0    1    1    0    0    1    0       = 2^3 + 2^1 + 2^0 + 2^-3 = 11.125
2^3  2^2  2^1  2^0  2^-1 2^-2 2^-3 2^-4

上例中的定点数称为 4.4 定点数,因为整数部分有 4 位,小数部分有 4 位。在 32 位类型中,定点值通常采用 16.16 格式,但也可以是 24.8、28.4 或任何其他组合。

从浮点值转换为定点值涉及以下步骤:

  1. 将浮点数乘以 2^(类型的小数位数),例如。 2^8 为 24.8
  2. 如有必要,将结果四舍五入(只需添加 0.5),然后将其取整(或强制转换为整数类型),留下一个整数值。
  3. 将此值赋给定点类型。

显然,您可能会在数字的小数部分丢失一些精度。如果小数部分的精度很重要,那么定点格式的选择可以反映这一点——例如。使用 16.16 或 8.24 而不是 24.8。

如果您的定点数需要签名,也可以用同样的方式处理负值。

如果我的 Java 更强大,我会尝试一些代码,但我通常用 C 编写这样的东西,所以我不会尝试 Java 版本。此外,stacker 的版本对我来说看起来不错,除了它不提供四舍五入的可能性之外。他甚至向您展示了如何进行乘法运算(转换很重要!)

【讨论】:

  • 所有正确,如果您提供解决方案以便您的答案可以被接受,那就更好了。幸运的是,我有这个,我要把它放在这里:int number = Float.floatToRawIntBits(floatNumber);
  • 我也在学习这个定点的东西。在你的例子中,应该是 10.125*10^4=178 吗?相反,它等于 162。
  • 谢谢大眼睛的家伙!是的 - 我在 4.4 定点示例中的值是错误的。现在修好了。顺便说一句,您评论中的值应该是 2^4,而不是 10^4 :-)
【解决方案2】:

一个非常简单的定点转换示例,它展示了如何转换和乘以 PI 乘以 2。结果被转换回双精度,以证明在整数计算期间尾数没有丢失。

您可以使用 sin() 和 cos() 查找表等轻松扩展它。 如果您打算使用定点来查找 java 定点库,我会建议您。

public class Fix {

    public static final int FIXED_POINT = 16;
    public static final int ONE = 1 << FIXED_POINT;

    public static int mul(int a, int b) {
        return (int) ((long) a * (long) b >> FIXED_POINT);
    }

    public static int toFix( double val ) {
        return (int) (val * ONE);
    }

    public static int intVal( int fix ) {
        return fix >> FIXED_POINT;
    }

    public static double doubleVal( int fix ) {
        return ((double) fix) / ONE;
    }

    public static void main(String[] args) {
        int f1 = toFix( Math.PI );
        int f2 = toFix( 2 );

        int result = mul( f1, f2 );
        System.out.println( "f1:" + f1 + "," + intVal( f1 ) );
        System.out.println( "f2:" + f2 + "," + intVal( f2 ) );
        System.out.println( "r:" + result +"," + intVal( result));
        System.out.println( "double: " + doubleVal( result ));

    }
}

输出

f1:205887,3
f2:131072,2
r:411774,6
double: 6.283172607421875

【讨论】:

  • +1 表示乘法。不过有两个改进建议:将double 转换为定点时提供舍入;并覆盖toString(),以便可以轻松打印定点值的正确解释(然后您可以在测试中使用)。
  • 我很好奇:fix &gt;&gt; FIXED_POINTfix / ONE是完全一样的操作吗?如果是这样,为什么要进行除法(我一直认为会慢一些)?另外,你能用&gt;&gt; FIXED_POINT解释乘法是必需的吗?我看到一些消息来源,他们说如果每个数字有m 十进制位,则移位必须是2m(所以2*FIX_POINT):allaboutcircuits.com/technical-articles/…
【解决方案3】:

定点类型是在小数点之后具有固定数量的小数/二进制位的类型。或者更一般地说,一种可以为某个正整数 N 存储 1/N 的倍数的类型。

在内部,定点数存储为乘以比例因子的值。例如,缩放因子为 100 的 123.45 被存储为整数 12345。

要将定点数的内部值转换为浮点数,只需除以比例因子即可。换一种方式,乘以比例因子并四舍五入到最接近的整数。

【讨论】:

    【解决方案4】:

    32 位定点的定义可能会有所不同。定点的一般概念是您在小数点(或二进制点)之前有一些固定数量的位,在小数点(或二进制点)之后有另一个固定数量的位。对于 32 位,最常见的分割可能是偶数(之前 16,之后 16),但根据目的,不能保证这一点。

    就转换而言,它再次对一些变化开放 - 例如,如果输入数字超出目标范围,您可能想要执行任意数量的不同操作(例如,在某些情况下环绕可能是有道理的,但在其他情况下,饱和度可能是首选)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-04-27
      • 1970-01-01
      相关资源
      最近更新 更多