1

Say I have 2 double values. One of them is very large and one of them is very small.

double x = 99....9;  // I don't know the possible max and min values,
double y = 0,00..1;  // so just assume these values are near max and min.

If I add those values together, do I lose precision?

In other words, does the max possible double value increase if I assign an int value to it? And does the min possible double value decrease if I choose a small integer part?

double z = x + y;    // Real result is something like 999999999999999.00000000000001
Utku Ufuk
  • 318
  • 1
  • 10
  • 24
  • See [here](http://stackoverflow.com/questions/177506/why-do-i-see-a-double-variable-initialized-to-some-value-like-21-4-as-21-3999996) – Dima Jan 08 '15 at 12:16
  • 2
    If you worry about precision, don't use `double`, use `BigDecimal`. – geert3 Jan 08 '15 at 12:18
  • @geert3 `BigDecimal` gives no guarantee of keeping precision, either---as soon as you need division. – Marko Topolnik Jan 08 '15 at 12:19
  • 2
    @MarkoTopolnik sure it does. You only need to specify your desired precision yourself. e.g. `new BigDecimal(a).divide(new BigDecimal(b), 5, RoundingMode.HALF_UP);` – geert3 Jan 08 '15 at 12:20
  • 1
    `BigDecimal three = new BigDecimal(3); System.out.println(ONE.divide(three, 5, HALF_UP).multiply(three));` prints `0.99999`. Most people would call that "loss of precision". Maybe you have some fancy definition in mind where it is called something else. – Marko Topolnik Jan 08 '15 at 12:39
  • There is no such thing as infinite precision, but BigDecimal can grow to any desired (finite) precision. – geert3 Jan 08 '15 at 12:40
  • @geert3 Again, that's loss of precision. A `BigRational` would be closed under division. Main point: if you worry about precision, `BigDecimal` is not your silver bullet. – Marko Topolnik Jan 08 '15 at 12:43
  • This is a theoretical discussion. Don't use computers if you want infinite precision. Don't use decimal numbers if you want fractions like 10/3 to be represented without loss of precisions. BigDecimal is the practical answer to these kind of issues. – geert3 Jan 08 '15 at 12:45
  • @geert3 No, that is not the practical answer to all kinds of issues with precision. The true advice is to carefully consider what operations you'll be performing and choose the representation which will satisfy your needs in finite space. You may just get lucky with `BigDecimal`, but division is not exactly an exotic operation. – Marko Topolnik Jan 08 '15 at 12:47
  • @MarkoTopolnik agree that you still need to carefully consider what you're doing. I imply that with most of my answers on SO ;-) – geert3 Jan 08 '15 at 12:48

3 Answers3

4

double values are not evenly distributed over all numbers. double uses the floating point representation of the number which means you have a fixed amount of bits used for the exponent and a fixed amount of bits used to represent the actual "numbers"/mantissa.

So in your example using a large and a small value would result in dropping the smaller value since it can not be expressed using the larger exponent.

The solution to not dropping precision is using a number format that has a potentially growing precision like BigDecimal - which is not limited to a fixed number of bits.

light_303
  • 2,101
  • 2
  • 18
  • 35
1

I'm using a decimal floating point arithmetic with a precision of three decimal digits and (roughly) with the same features as the typical binary floating point arithmetic. Say you have 123.0 and 4.56. These numbers are represented by a mantissa (0<=m<1) and an exponent: 0.123*10^3 and 0.456*10^1, which I'll write as <.123e3> and <.456e1>. Adding two such numbers isn't immediately possible unless the exponents are equal, and that's why the addition proceeds according to:

 <.123e3>   <.123e3>
 <.456e1>   <.004e3>
            --------
            <.127e3>

You see that the necessary alignment of the decimal digits according to a common exponent produces a loss of precision. In the extreme case, the entire addend could be shifted into nothingness. (Think of summing an infinite series where the terms get smaller and smaller but would still contribute considerably to the sum being computed.)

Other sources of imprecision result from differences between binary and decimal fractions, where an exact fraction in one base cannot be represented without error using the other one.

So, in short, addition and subtraction between numbers from rather different orders of magnitude are bound to cause a loss of precision.

laune
  • 31,114
  • 3
  • 29
  • 42
0

If you try to assign too big value or too small value a double, compiler will give an error:

try this

    double d1 =  1e-1000;
    double d2 =  1e+1000;
Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275