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

如何在Java中将IEEE-754二进制表示字符串转换为浮点或双精度?,java,string,floating-point,ieee-754,string-parsing,Java,String,Floating Point,Ieee 754,String Parsing,由于所有Java浮点数(浮点数和双精度浮点数)都在内部表示为位,我想找到一个有效的算法来转换一个表示浮点或双精度位的字符串,并将其转换为相应的浮点数-我找不到它的内置库函数,所以我求助于自己编写它 长度为32的二进制字符串表示浮点,其中长度为64的二进制字符串将转换为双精度。所有浮点数都可以转换为双精度浮点数,而不会降低精度。空格被忽略 示例 “0 10000000 10010010000111111011011011011011011011”变为浮点数形式的3.141592 “1111111

由于所有Java浮点数(浮点数和双精度浮点数)都在内部表示为位,我想找到一个有效的算法来转换一个表示浮点或双精度位的字符串,并将其转换为相应的浮点数-我找不到它的内置库函数,所以我求助于自己编写它

长度为32的二进制字符串表示浮点,其中长度为64的二进制字符串将转换为双精度。所有浮点数都可以转换为双精度浮点数,而不会降低精度。空格被忽略

示例

  • “0 10000000 10010010000111111011011011011011011011”
    变为浮点数形式的
    3.141592
  • “11111111 00000000000000000000000”
    变为
    -无限
  • “0 11111111 1001001000011111011011”
    变成浮点
    NaN
  • “1 1000000000 010110111111000010101010001011000101000010111011010001”

    成为最接近-e的双精度值,即
    2.71828182845904050909559829843
到目前为止,我有大量的代码:

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二进制表示字符串转换为其
float
double
的最简洁或最快的方法是什么?最好采用最有效的方法,并充分说明其效率和专业知识。

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

  • 从字符串中删除空格
  • 验证字符串长度
  • 将二进制字符串转换为
    int
  • 调用
    Float.intBitsToFloat(int)
    转换为
    Float
  • 对于双打,使用
    long
    和等效的
    Double
    方法


    简化的代码是否更有效


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

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

  • 从字符串中删除空格
  • 验证字符串长度
  • 将二进制字符串转换为
    int
  • 调用
    Float.intBitsToFloat(int)
    转换为
    Float
  • 对于双打,使用
    long
    和等效的
    Double
    方法


    简化的代码是否更有效


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

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

    return Float.intBitsToFloat(Integer.parseUnsignedInt(binString, 2));
    
    • Integer.parseUnsignedInt(binString,2)
      将二进制数字中的无符号int从0到232-1转换为
      int
      表示形式。
      parseInt(…)
      不起作用,因为
      parseInt
      在其
      binString
      中包含一个显式符号,如果它表示负int,则需要一个前导连字符,而不是231或更大的值。类似地,
      Long.parseUnsignedLong(binString,2)
      64位大小写的应用程序

    • Float.intBitsToFloat(int n)
      表示浮点值,其内部存储的位与int值
      n
      相同。类似地,
      Double.longBitsToDouble(long n)
      适用于64位大小写

    • 使用“方法组合”,此行首先将(无符号)二进制字符串转换为相应的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");
        }
    }
    

    从@StephenC开始,将IEEE-754二进制表示转换为相应浮点值的改进代码只占用一行:

    return Float.intBitsToFloat(Integer.parseUnsignedInt(binString, 2));
    
    • Integer.parseUnsignedInt(binString,2)
      将二进制数字中的无符号int从0到232-1转换为
      int
      表示形式。
      parseInt(…)
      不起作用,因为
      parseInt
      在其
      binString
      中包含一个显式符号,如果它表示负int,则需要一个前导连字符,而不是231或更大的值。类似地,
      Long.parseUnsignedLong(binString,2)
      64位大小写的应用程序

    • Float.intBitsToFloat(int n)
      表示浮点值,其内部存储的位与int值
      n
      相同。类似地,
      Double.longBitsToDouble(long n)
      适用于64位大小写

    • 使用“方法组合”,此行首先将(无符号)二进制字符串转换为相应的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");
        }
    }
    

    这个问题不是关于将“二进制”十进制转换成浮点。如果你想改进已经可以工作的代码,你可能应该试试@StephenC双精度的情况如何?简化后的代码是否更有效?这个问题不是关于将“二进制”十进制转换为浮点。如果您希望改进已经有效的代码,您可能应该尝试@StephenC。双精度的情况如何?简化的代码是否更有效?在进行基准测试时,您的方法是否确实更快?我的“低效”算法看起来像是转换ieee754浮点表示的“更幼稚”的方法。1)请随意编写自己的基准:-)2)是的。我的方法避免了那些乱七八糟的东西。在幕后
    intBitsToFloat
    将是一个简单的任务。当进行基准测试时,您的方法肯定更快吗?我的“低效”算法看起来像是转换ieee754浮点表示的“更幼稚”的方法。1)请随意编写