如何将 IEEE-754 二进制表示字符串转换为 Java 中的浮点数或双精度数?

How can I convert an IEEE-754 binary representation String to a float or double in Java?

由于所有 Java 浮点数,即 floatsdoubles,在内部都表示为位,我想要找到一个 efficient 算法来转换表示 floatdouble 的位的字符串并转换它转换成相应的浮点数 - 我找不到它的内置库函数所以我求助于自己编写它。

长度为 32 的二进制字符串表示 float,其中长度为 64 的二进制字符串将转换为 double。所有 floats 都可以转换为 doubles 而不会损失准确性。忽略空格。

例子

到目前为止我有这么一大堆代码:

public static double ieee(String binString) throws Exception {
    binString = binString.replace(" ", "");
    if (binString.length() == 32) {
        String exponentB = binString.substring(1, 9);
        String mantissaB = binString.substring(9, 32);
        int sgn = binString.charAt(0) == '0' ? 1 : -1;
        int exponent = Integer.parseInt(exponentB, 2) - 127; // Biased by 127
        double mantissa = 1 + Integer.parseInt(mantissaB, 2) / Math.pow(2, 23);

        if (exponent == 128 && mantissa == 1)
            return sgn == 1 ? Double.POSITIVE_INFINITY : Double.NEGATIVE_INFINITY;
        if (exponent == 128 && mantissa != 0)
            return Double.NaN;
        if (exponent == -127)
            return sgn*Math.pow(2,-126)*(mantissa - 1);
        return sgn*Math.pow(2, exponent)*mantissa;
    }
    else if (binString.length() == 64) {
        String exponentB = binString.substring(1, 12);
        String mantissaB = binString.substring(12, 64);
        int sgn = binString.charAt(0) == '0' ? 1 : -1;
        int exponent = Integer.parseInt(exponentB, 2) - 1023; // Biased by 1023
        double mantissa = 1 + Long.parseLong(mantissaB, 2) / Math.pow(2, 52);

        if (exponent == 1024 && mantissa == 1)
            return sgn == 1 ? Double.POSITIVE_INFINITY : Double.NEGATIVE_INFINITY;
        if (exponent == 1024 && mantissa != 0)
            return Double.NaN;
        if (exponent == -1023)
            return sgn*Math.pow(2,-1022)*(mantissa - 1);
        return sgn*Math.pow(2, exponent)*mantissa;
    }
    else {
        throw new Exception("Does not represent internal bits of a floating-point number");
    }
}

尽管我的代码目前有效,但就速度和数量而言,将 IEEE-754 二进制表示字符串转换为其 floatdouble 的最简洁或最快的方法是什么代码?优先考虑最有效的方法,并能很好地解释其效率和专业知识。

这种方法可能更有效。它当然更简单,更易于维护。

  1. 从字符串中删除空格
  2. 验证字符串长度...
  3. 将二进制字符串转换为int
  4. 调用 Float.intBitsToFloat(int) 转换为 float

对于双打,使用 long 和等效的 Double 方法。


Is the simplified code more efficient?

唯一可以确定的方法是对其进行基准测试。但是根据您的代码所做的,我相信是这样。

来自@StephenC,将IEEE-754二进制表示转换为相应浮点值的改进代码仅占一行:

return Float.intBitsToFloat(Integer.parseUnsignedInt(binString, 2));
  • Integer.parseUnsignedInt(binString, 2) 将二进制数字中的 unsigned int 从范围 0 转换为 232-1到 int 表示。 parseInt(...) 不起作用,因为 parseInt 在其 binString 中包含一个显式符号,如果它表示负整数,则需要前导连字符而不是 2[=36 的值=]31 或更高。同样,Long.parseUnsignedLong(binString, 2) 适用于 64 位情况。

  • Float.intBitsToFloat(int n) 表示内部存储与 int 值 n 相同位的浮点值。同样,Double.longBitsToDouble(long n) 适用于 64 位情况。

  • 使用"method composition",这一行首先将(无符号)二进制字符串转换为其对应的int,然后将其转换为具有相同存储位的浮点值。

最终代码为

public static double ieeeToFloat(String binString) throws Exception {
    binString = binString.replace(" ", "");
    /* 32-bit */
    if (binString.length() == 32) {
        return Float.intBitsToFloat(Integer.parseUnsignedInt(binString, 2));
    }
    /* 64-bit */
    else if (binString.length() == 64) {
        return Double.longBitsToDouble(Long.parseUnsignedLong(binString, 2));
    }
    /* An exception thrown for mismatched strings */
    else {
        throw new Exception("Does not represent internal bits of a floating-point number");
    }
}