在 Java 中将浮点转换为 32 位定点

2022-09-04 05:32:12

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

无法理解什么是32位定点?

任何身体都可以帮助算法吗?


答案 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版本。此外,堆叠器的版本对我来说看起来不错,除了一个小的例外,它没有提供舍入的可能性。他甚至向你展示了如何执行乘法(这种转变很重要!


答案 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