Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java repeating decimal in simple equation

Tags:

java

I am doing a school assignment in which I solve an equation involving coordinates in a circle (r^2 = x^2 + y^2) were r = 1, and you increment through x values solving for y. I am getting a repeating decimals even though I only incrementing in tenths. I have no idea why and have tried it in a few different ways. Here is the code.

    double r = 1;
    double rSqr;
    double x = 1;
    double xSqr;
    double y;
    double ySqr;
    double inc = 0.1;
    int count = 0;
    while(x > -r)
    {
        x = r - (count * inc);
        rSqr = Math.pow(r, 2);
        xSqr = Math.pow(x, 2);
        ySqr = rSqr - xSqr;
        y = Math.sqrt(ySqr);
        count++;
        System.out.println(x + " " + y);
    }

and the output is this

1.0 0.0
0.9 0.4358898943540673
0.8 0.5999999999999999
0.7 0.714142842854285
0.6 0.8
0.5 0.8660254037844386
0.3999999999999999 0.9165151389911681
0.29999999999999993 0.9539392014169457
0.19999999999999996 0.9797958971132712
0.09999999999999998 0.99498743710662
0.0 1.0
-0.10000000000000009 0.99498743710662
-0.20000000000000018 0.9797958971132712
-0.30000000000000004 0.9539392014169457
-0.40000000000000013 0.9165151389911679
-0.5 0.8660254037844386
-0.6000000000000001 0.7999999999999999
-0.7000000000000002 0.7141428428542849
-0.8 0.5999999999999999
-0.9000000000000001 0.43588989435406705
-1.0 0.0
like image 558
Tyler Lall Avatar asked Mar 06 '26 21:03

Tyler Lall


2 Answers

The problem is that double is imprecise. It uses 64 bits to represent decimal numbers; some bits are used for the numeric part, and some for the exponent, but many seemingly simple decimal numbers can not be accurately represented in this way, for example 0.1. See this wiki article for more.

One way around the problem is to display the number using DecimalFormat, which can round the number for presentation purposes. Here's some example code:

public static void main(String[] args) {
    DecimalFormat decimalFormat = new DecimalFormat("#0.000");
    double d = 1 - .9; // one way to get a repeating decimal floating point number 
    System.out.println(d);
    System.out.println(decimalFormat.format(d));
}

Output:

0.09999999999999998
0.100
like image 172
Bohemian Avatar answered Mar 08 '26 09:03

Bohemian


It is the IEEE 754 floating point representation.

Use BigDecimal as datatype instead of double to solve your problem. But take care as BigDecimal is immutable.

        BigDecimal r = BigDecimal.ONE;
        BigDecimal rSqr;
        BigDecimal x = BigDecimal.ONE;
        BigDecimal xSqr;
        BigDecimal y;
        BigDecimal ySqr;
        BigDecimal inc = new BigDecimal("0.1");
        int count = 0;

        while(x.compareTo(r.negate())>0)
        {
        // i'll let you fill in this part
        }
like image 42
Frank Avatar answered Mar 08 '26 10:03

Frank