Java如何将浮点数转换为字符串

5

这是我正在查看的内容:

float p=1.15f;
BigDecimal bdp=new BigDecimal(p);
float q=1.1499999f;
float r=1.14999999f;

System.out.println(p);   //1.15
System.out.println(bdp); //1.14999997615814208984375
System.out.println(q);   //1.1499999
System.out.println(r);   //1.15

所以我理解“p”的十进制值1.15无法在二进制中精确表示。
因此,大的big decimal“bdp”输出对我来说是完全有意义的...那就是浮点数的实际值。
问题1
当将浮点数“p”转换回字符串进行输出(如1.15),舍入是在哪里/如何发生的(从内部值1.149..375到1.15)?
它在文档中的哪里规定?toString javadoc并没有真正帮助我。
我在the language spec中看到了这个:
浮点类型和双精度类型的元素是可以使用IEEE 754 32位单精度和64位双精度二进制浮点格式表示的值。 Wikipedia的IEEE 754文章提供了以下内容:

这可以提供6到9个有效十进制数字的精度(如果将最多具有6个有效十进制数字的十进制字符串转换为IEEE 754单精度,然后将其转换回相同数量的有效十进制数字,则最终字符串应与原始字符串匹配;

问题2
所以看起来这就是Java / IEEE 754浮点数应该工作的方式?

我得到了一定数量的float / string转换/表示的准确性(例如“p”和“q”),如果超过了该数字,Java将对显示进行一些舍入(例如“r”)?

感谢您的帮助。


除非你在进行科学计算,否则请停止使用浮点数。 - DwB
没错。我们的代码中使用了BigDecimal。但是我们从另一个系统中获取到了double类型的数据,我需要了解这些细节,以便尽可能准确地处理所获取的数据。谢谢。 - matt1616
1
如果您对这种问题感兴趣,考虑使用 System.out.println(new BigDecimal(someFloat)); 来获取 someFloat 的精确十进制表示。 - Patricia Shanahan
3个回答

8
我认为这是Javadoc中涉及到你所寻找的行为的相关部分(来自于 static String toString(float) 方法):

必须打印m或a的小数部分有多少位数字?至少必须有一位数字来表示小数部分,除此之外,还需要尽可能多的数字,但只有足以唯一地区分类型为float的相邻值的数字。

换句话说:对于浮点数类型的toString方法通常会产生最短的十进制表示,可以明确地识别浮点数的真实值。
以下是示例程序:
import java.math.BigDecimal;

public class FloatTest {

  static void show(float f) {
    BigDecimal f_exact = new BigDecimal(f);
    System.out.println("---");
    System.out.println("String value: " + f);
    System.out.println("Exact value:  " + f_exact);
    System.out.println("Delta:        " + 
        new BigDecimal("1.15").subtract(f_exact));
  }

  public static void main(String[] args) {
    show(1.15f);
    show(Math.nextUp(1.15f));
  }
}

输出:

---
String value: 1.15
Exact value:  1.14999997615814208984375
Delta:        2.384185791015625E-8
---
String value: 1.1500001
Exact value:  1.150000095367431640625
Delta:        -9.5367431640625E-8

好的,谢谢,你说得对。我之前看过那个,但直到现在才真正明白。 - matt1616

4

谢谢 mttdbrd...这很有帮助。根据您的第一段话,我认为对我的问题的答案是:是的,Java会按照IEEE规范在内部进行四舍五入。

这里是一个程序的输出,让我看到了一些四舍五入的示例:

-------------------------------------------
string            1.49999
bigdec of float   1.499989986419677734375
float back to str 1.49999
-------------------------------------------
string            1.4999991
bigdec of float   1.49999904632568359375
float back to str 1.499999
-------------------------------------------
string            1.4999992
bigdec of float   1.49999916553497314453125
float back to str 1.4999992
-------------------------------------------
string            1.4999993
bigdec of float   1.4999992847442626953125
float back to str 1.4999993
-------------------------------------------
string            1.4999994
bigdec of float   1.49999940395355224609375
float back to str 1.4999994
-------------------------------------------
string            1.4999995
bigdec of float   1.499999523162841796875
float back to str 1.4999995
-------------------------------------------
string            1.4999996
bigdec of float   1.49999964237213134765625
float back to str 1.4999996
-------------------------------------------
string            1.4999997
bigdec of float   1.49999964237213134765625
float back to str 1.4999996
-------------------------------------------
string            1.4999998
bigdec of float   1.4999997615814208984375
float back to str 1.4999998
-------------------------------------------
string            1.4999999
bigdec of float   1.49999988079071044921875
float back to str 1.4999999
-------------------------------------------
string            1.15
bigdec of float   1.14999997615814208984375
float back to str 1.15
-------------------------------------------
string            1.49999964237213134765626
bigdec of float   1.49999964237213134765625
float back to str 1.4999996

如果有人需要,这里是程序代码:

public static void floatAccuracy3()
{
    printFloatAndBigDec("1.49999");
    for (int i = 1; i < 10; i++) {
        String s="1.499999";
        s+=i;
        printFloatAndBigDec(s);         
    }
    printFloatAndBigDec("1.15");
    printFloatAndBigDec("1.49999964237213134765626");
}

public static void printFloatAndBigDec(String s)
{
    Float f=new Float(s);
    BigDecimal bdf=new BigDecimal(f);
    System.out.println("-------------------------------------------");
    System.out.println("string            "+s);
    System.out.println("bigdec of float   "+bdf);
    System.out.println("float back to str "+f);
}

以下是一些其他链接,如果有任何人在研究这方面的内容时需要帮助,它们可能会有所帮助:


2

来自JLS,4.2.4.浮点数运算:

Java编程语言要求浮点数算术运算的行为就好像每个浮点数运算符将其浮点数结果舍入到结果精度一样。不精确的结果必须舍入到最接近无限精确结果的可表示值;如果两个最近的可表示值同样接近,则选择其最低有效位为零的那个。这是IEEE 754标准的默认舍入模式称为四舍五入。

Java编程语言在将浮点值转换为整数时(§5.1.3)使用向零舍入,这在这种情况下的作用就像截断数字,丢弃尾数位。向零舍入选择其结果与无限精确结果最接近且不大于其格式值的格式。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接