由于所有Java浮点数( floats 和 doubles )在内部都表示为位,因此我想找到一种效率算法,将代表该 float 或 double 的位的字符串转换为对应的浮点数-我找不到内置的库函数,所以我只能自己编写。
长度为32的二进制字符串表示 float ,其中长度为64的二进制字符串将转换为 double 。所有 floats 都可以转换为 doubles ,而不会损失准确性。空格将被忽略。
示例
"0 10000000 10010010000111111011011"
成为<{> float 的3.141592
。"1 11111111 00000000000000000000000"
成为-infinity
。"0 11111111 10010010000111111011011"
成为 float NaN
。"1 10000000000 0101101111110000101010001011000101000101011101101001"
2.71828182845904509079559829843
到目前为止,我有这么大量的代码:
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
吗?最好使用最能说明其效率和专业知识的方法。
答案 0 :(得分:3)
这种方法可能更有效。当然,它更简单,更易于维护。
int
Float.intBitsToFloat(int)
转换为float
。对于双打,请使用long
和等效的Double
方法。
简化代码更有效吗?
唯一可以确定的方法是对其进行基准测试。但是,根据您的代码在做什么,我相信。
答案 1 :(得分:0)
从@StephenC 起,用于将IEEE-754二进制表示形式转换为其对应的浮点值的改进代码仅占用一行:
return Float.intBitsToFloat(Integer.parseUnsignedInt(binString, 2));
Integer.parseUnsignedInt(binString, 2)
将范围从0到2 32 -1的二进制数字 unsigned int转换为int
表示形式。 parseInt(...)
不起作用,因为parseInt
在其binString
中包含显式符号,并且如果它表示负整数,则需要前导连字符而不是2 31 或更高。同样,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");
}
}