由于所有Java浮点数(浮点数和双精度浮点数)在内部都表示为位,因此我想找到一种有效的算法来转换表示该浮点数或双精度浮点数位的字符串,并将其转换为相应的浮点数-我找不到它的内置库函数,所以我求助于自己编写它。
长度为32的二进制字符串表示浮点,其中长度为64的二进制字符串将转换为double。所有浮点数都可以转换为双精度浮点数,而不会损失精度。将忽略空格。
到目前为止,我有这么多代码:
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二进制表示字符串转换为其浮点数
或双
的最简洁或最快的方法是什么?最好是能很好地解释其效率和专业知识的最有效的方法。
public class IEEE754ToFloatingValues {
public static double convertToInt(String mantissa_str) {
int power_count = -1;
double mantissa_int = 0.0;
for (int i = 0; i < mantissa_str.length(); i++) {
// System.out.print(Integer.parseInt(mantissa_str.charAt(i) + ""));
mantissa_int += (Integer.parseInt(mantissa_str.charAt(i) + "") * Math.pow(2, power_count));
power_count -= 1;
}
return mantissa_int + 1.0;
}
public static String convertToBinary(int i) {
return Integer.toBinaryString(i + 0b10000).substring(1);
}
public static String decimalToHex(String decimal) {
int i = Integer.parseInt(decimal);
System.out.println("<<>>" + i);
String my_hexdata = Integer.toHexString(i);
System.out.println(my_hexdata);
return String.valueOf(ReturnFloatingValue(my_hexdata));
}
public static double ReturnFloatingValue(String my_hexdata) {
String myString = "";
if (my_hexdata == null) {
return -2.0;
}
if (my_hexdata.length() != 8) {
myString = String.format("%1$-" + 8 + "s", my_hexdata).replace(' ', '0');
System.out.println("My hex data after appending 0's is : " + myString);
}
String binary = "";
for (int i = 0; i < myString.length(); i++) {
int num = Integer.parseInt(myString.charAt(i) + "", 16);
binary += convertToBinary(num);
}
System.out.println("Binary length is : " + binary.length());
System.out.println("Binary number is : " + binary);
if (binary == null || binary.isEmpty()) {
return -3.0;
}
String ieee_32 = binary.substring(2);
ieee_32 = String.format("%1$-32s", binary).replace(' ', '0');
long sign_bit = Long.parseLong(new StringBuilder().append(ieee_32.charAt(0)).toString());
long exponent_bias = Long.parseLong(ieee_32.substring(1, 9), 2);
long exponent_unbias = exponent_bias - 127L;
System.out.println("Exponent unbias is : " + exponent_unbias);
String mantissa_str = ieee_32.substring(9);
double mantissa_int = convertToInt(mantissa_str);
double real_no = Math.pow(-1.0, (double) sign_bit) * mantissa_int * Math.pow(2.0, (double) exponent_unbias);
System.out.println("Real no is : " + real_no);
return real_no;
}
public static void main(String[] args) {
//decimalToHex("16547");
}
}
从@StephenC,将IEEE-754二进制表示转换为其相应浮点值的改进代码只占用一行:
return Float.intBitsToFloat(Integer.parseUnsignedInt(binString, 2));
>
<代码>整数。parseUnsignedInt(binString,2)将0到2的二进制数字中的无符号int转换为int的表示形式。parseInt(…)不起作用,因为parseInt在其binString中包含一个显式符号,如果它表示负int,则需要一个前导连字符,而不是大于等于2的值。类似地,<代码>长。parseUnsignedLong(binString,2)64位大小写的应用程序。
<代码>浮动。intBitsToFloat(int n)表示浮点值,其内部存储的位与int值相同。类似地,<代码>双精度。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");
}
}
这种方法可能更有效。它肯定更简单、更易于维护。
对于双精度,使用long
和等效的Double
方法。
简化的代码是否更有效?
唯一确定的方法是对其进行基准测试。但基于您的代码所做的,我相信是这样的。
问题内容: 我正在尝试将以下十六进制字符串转换为“ 41630D54FFF68872”到9988776.0(float-64)。 使用单精度float-32,我可以这样做: 但这会引发:java.lang.NumberFormatException:使用上面的64位十六进制时,Infinite或NaN。 如何将十六进制转换为使用64位IEEE-754编码的双精度浮点数? 谢谢 问题答案: 您需要双
问题内容: 与浮点变量一起使用时出现问题(向下舍入/截断精度部分)。如何正确执行? 游乐场:https : //play.golang.org/p/49TjJwwEdEJ 输出: 我期望的输出是的,但实际产量。 问题答案: 原始问题: Golang中的楼层号不正确 将Math.Floor与float变量一起使用时出现问题(向下舍入/截断精度部分)。我该怎么做呢? 我预计1980 * 0.1 / 1
问题内容: 我想将二进制数转换为浮点数。这是一种可能性的示例: 给我正确的输出: 不幸的是,我正在使用二进制 字符串 ,即,我需要类似的东西。 但是,这不起作用: 我尝试使用它将带引号的可打印数据块转换回二进制并返回二进制数据。但是最终,我得到了同样的错误: 我了解输出数字是整数的情况,但是如果我想获得数字12.546怎么办?那么该函数对二进制字符串的调用是什么样的? 问题答案: 另一种选择是做
与十进制相似,二进制数也可以表示浮点。现在我读到它可以有类似的浮动 :,:,:...等等。但是,例如,0.1(十进制)如何用二进制表示? 另外,给定一个十进制浮点数,如何将其转换为十进制等价物(假设它不是那么简单)。 编辑:所以我知道更好的问题应该是;如何将十进制浮点转换为二进制?现在我知道我们乘以小数部分,直到它变成零。现在很有可能两个浮点可以有相同的表示,对吗?
我的意思是,例如,我用IEEE-754单精度编码了以下数字: 上面的二进制数存储在文本字符串中。 问题是,如何在不丢失精度的情况下将这个字符串转换为IEEE-754双精度表示(有点像下面的,但值不同)? 这是用IEEE-754双精度编码的< del >相同的数。 我已经尝试使用下面的算法将第一个字符串先转换回十进制数,但它失去了精度。 我在Windows平台上使用Qt C框架。 编辑:我必须道歉,
我在哪里可以找到这样的代码?我尝试了GNU类路径的源代码,但它使用了一个本机方法进行这种转换。