how does Java convert floats to strings

后端 未结 3 771
广开言路
广开言路 2021-01-03 04:11

Here\'s what I\'m looking at:

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

System.out.println(p);   //1.15
Syst         


        
相关标签:
3条回答
  • 2021-01-03 04:52

    Thanks mttdbrd ... that helps. From your first paragraph then I think that the answer to my question is: yes, Java does this rounding internally in accordance with the IEEE spec.

    Here's the output of a program that let's me see a little bit of that rounding in action:

    -------------------------------------------
    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
    

    And here's the program if anyone wants it:

    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);
    }
    

    And some other links in case they're helpful to anyone else researching this stuff:

    • floating point basics
    • princeton cs intro floating points
    • What Every Computer Scientist Should Know About Floating-Point Arithmetic
    • Why 0.1 Does Not Exist In Floating-Point
    • JLS 4.2.4 Floating-Point Operations
    • IEEE round to nearest
    0 讨论(0)
  • 2021-01-03 04:53

    I think this is the relevant part of the Javadoc that describes the behavior you're looking at (from the static String toString(float) method):

    How many digits must be printed for the fractional part of m or a? There must be at least one digit to represent the fractional part, and beyond that as many, but only as many, more digits as are needed to uniquely distinguish the argument value from adjacent values of type float.

    To paraphrase: the toString methods for floating-point types will generally produce the shortest decimal representation that can unabmiguously identify the true value of the floating-point number.

    Example program to illustrate:

    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));
      }
    }
    

    Output:

    ---
    String value: 1.15
    Exact value:  1.14999997615814208984375
    Delta:        2.384185791015625E-8
    ---
    String value: 1.1500001
    Exact value:  1.150000095367431640625
    Delta:        -9.5367431640625E-8
    
    0 讨论(0)
  • 2021-01-03 05:11

    From the JLS, 4.2.4. Floating-Point Operations:

    The Java programming language requires that floating-point arithmetic behave as if every floating-point operator rounded its floating-point result to the result precision. Inexact results must be rounded to the representable value nearest to the infinitely precise result; if the two nearest representable values are equally near, the one with its least significant bit zero is chosen. This is the IEEE 754 standard's default rounding mode known as round to nearest.

    The Java programming language uses round toward zero when converting a floating value to an integer (§5.1.3), which acts, in this case, as though the number were truncated, discarding the mantissa bits. Rounding toward zero chooses at its result the format's value closest to and no greater in magnitude than the infinitely precise result.

    0 讨论(0)
提交回复
热议问题